Merge commit '41bcbd14f0dd7c01d45570fd36ae0ecef1d38530' into beta

This commit is contained in:
Ali 2020-11-30 12:33:36 +04:00
commit c76c278457
2853 changed files with 1610006 additions and 340493 deletions

View File

@ -4,6 +4,9 @@ build --action_env=ZERO_AR_DATE=1
build --strategy=Genrule=local
build --apple_platform_type=ios
build --cxxopt='-std=c++14'
build --per_file_copt="third-party/webrtc/.*\.cpp$","@-std=c++14"
build --per_file_copt="third-party/webrtc/.*\.cc$","@-std=c++14"
build --per_file_copt="third-party/webrtc/.*\.mm$","@-std=c++14"
build --spawn_strategy=local
build --strategy=SwiftCompile=local
build --features=debug_prefix_map_pwd_is_dot

1
.gitignore vendored
View File

@ -27,6 +27,7 @@ DerivedData
buck-out/*
.buckd/*
tools/buck
tools/bazel
AppBinary.xcworkspace/*
Project.xcodeproj/*
Watch/Watch.xcodeproj/*

View File

@ -24,7 +24,7 @@ internal:
name: internal
artifacts:
paths:
- build/artifacts/Telegram.DSYMs.zip
- build/artifacts
expire_in: 1 week
experimental:

View File

@ -48,7 +48,7 @@ BAZEL=$(shell which bazel)
ifneq ($(BAZEL_HTTP_CACHE_URL),)
export BAZEL_CACHE_FLAGS=\
--remote_cache="$(BAZEL_HTTP_CACHE_URL)"
--remote_cache="$(BAZEL_HTTP_CACHE_URL)" --experimental_remote_downloader="$(BAZEL_HTTP_CACHE_URL)"
else ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_CACHE_FLAGS=\
--disk_cache="${BAZEL_CACHE_DIR}"
@ -57,6 +57,9 @@ endif
BAZEL_COMMON_FLAGS=\
--announce_rc \
--features=swift.use_global_module_cache \
--features=swift.split_derived_files_generation \
--features=swift.skip_function_bodies_for_derived_files \
--jobs=${CORE_COUNT}
BAZEL_DEBUG_FLAGS=\
--features=swift.enable_batch_mode \
@ -69,7 +72,9 @@ BAZEL_OPT_FLAGS=\
--features=swift.opt_uses_wmo \
--features=swift.opt_uses_osize \
--swiftcopt='-num-threads' --swiftcopt='0' \
--features=dead_strip \
--objc_enable_binary_stripping \
--apple_bitcode=watchos=embedded \
build_arm64: check_env
@ -403,13 +408,38 @@ bazel_app_debug_arm64:
bazel_app_arm64:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--objc_enable_binary_stripping=true \
--features=dead_strip \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_app_armv7:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7 \
--watchos_cpus=armv7k,arm64_32 \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
bazel_app:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7,arm64 \
--watchos_cpus=armv7k,arm64_32 \
--apple_generate_dsym \
--output_groups=+dsyms \
--verbose_failures
@ -417,21 +447,25 @@ bazel_app_arm64:
bazel_prepare_development_build:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/prepare-build.sh Telegram development
bazel_project: kill_xcode bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram
bazel_soft_project: bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
build-system/generate-xcode-project.sh Telegram
bazel_opt_project: bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
BAZEL_HTTP_CACHE_URL="${BAZEL_HTTP_CACHE_URL}" \
GENERATE_OPT_PROJECT=1 \
build-system/generate-xcode-project.sh Telegram

View File

@ -1 +1 @@
gCh0ST/jBZ+NM8mvcBcsd12A5FMFT4q6fETcWd5elO0=
E65Wt9QZyVD8tvGhCJD3My6x57eDORYaiYh6HR7T3fI=

View File

@ -130,6 +130,13 @@ filegroup(
], exclude = ["Telegram-iOS/DefaultAppIcon.xcassets/**/.*"]),
)
filegroup(
name = "BlackAppIcon",
srcs = glob([
"Telegram-iOS/BlackIcon.xcassets/**/*",
], exclude = ["Telegram-iOS/BlackIcon.xcassets/**/.*"]),
)
filegroup(
name = "DefaultIcon",
srcs = glob([
@ -177,6 +184,7 @@ swift_library(
],
deps = [
"//submodules/TelegramUI:TelegramUI",
"//third-party/boringssl:crypto",
],
)
@ -244,9 +252,9 @@ official_bundle_ids = [
"org.telegram.Telegram-iOS",
]
apple_pay_merchants = official_apple_pay_merchants if telegram_bundle_id == "ph.telegra.Telegraph" else ""
apple_pay_merchants = official_apple_pay_merchants if telegram_bundle_id == "ph.telegra.Telegraph" else []
apple_pay_merchants_fragment = "" if apple_pay_merchants == "" else """
apple_pay_merchants_fragment = "" if apple_pay_merchants == [] else """
<key>com.apple.developer.in-app-payments</key>
<array>
""" + "\n".join([
@ -286,6 +294,8 @@ telegram_entitlements_template = """
</array>
<key>application-identifier</key>
<string>{telegram_team_id}.{telegram_bundle_id}</string>
<key>com.apple.developer.icloud-container-environment</key>
<string>{telegram_icloud_environment}</string>
""" + apple_pay_merchants_fragment + unrestricted_voip_fragment
plist_fragment(
@ -295,6 +305,7 @@ plist_fragment(
telegram_bundle_id = telegram_bundle_id,
telegram_team_id = telegram_team_id,
telegram_aps_environment = telegram_aps_environment,
telegram_icloud_environment = "Production" if telegram_aps_environment == "production" else "Development",
)
)
@ -451,6 +462,8 @@ plist_fragment(
</array>
<key>WKWatchKitApp</key>
<true/>
<key>CFBundlePackageType</key>
<string>APPL</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
)
@ -523,6 +536,8 @@ plist_fragment(
<string>MtProtoKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -564,6 +579,8 @@ plist_fragment(
<string>SwiftSignalKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -605,6 +622,8 @@ plist_fragment(
<string>Postbox</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -649,6 +668,8 @@ plist_fragment(
<string>TelegramApi</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -690,6 +711,8 @@ plist_fragment(
<string>SyncCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -735,6 +758,8 @@ plist_fragment(
<string>TelegramCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -759,7 +784,7 @@ ios_framework(
":SwiftSignalKitFramework",
":PostboxFramework",
":SyncCoreFramework",
":TelegramApiFramework",
#":TelegramApiFramework",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -783,6 +808,8 @@ plist_fragment(
<string>AsyncDisplayKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -824,6 +851,8 @@ plist_fragment(
<string>Display</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -847,6 +876,33 @@ genrule(
]
)
genrule(
name = "GenerateAddAlternateIcons",
srcs = [
"Telegram-iOS/AddAlternateIcons.sh",
],
cmd_bash =
"""
cat $(location Telegram-iOS/AddAlternateIcons.sh) >> $(location AddAlternateIcons.sh)
""",
outs = [
"AddAlternateIcons.sh",
],
executable = True,
visibility = [
"//visibility:public",
]
)
sh_binary(
name = "AddAlternateIcons",
data = [
"Telegram-iOS/AlternateIcons.plist",
"Telegram-iOS/AlternateIcons-iPad.plist",
],
srcs = [":GenerateAddAlternateIcons"],
)
ios_framework(
name = "DisplayFramework",
bundle_id = "{telegram_bundle_id}.Display".format(
@ -885,6 +941,8 @@ plist_fragment(
<string>TelegramUI</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
@ -908,7 +966,7 @@ ios_framework(
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramApiFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
":TelegramCoreFramework",
":AsyncDisplayKitFramework",
@ -1090,6 +1148,10 @@ plist_fragment(
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
""".format(
telegram_bundle_id = telegram_bundle_id,
)
@ -1207,7 +1269,8 @@ ios_extension(
frameworks = [
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramApiFramework",
":TelegramCoreFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
],
)
@ -1258,8 +1321,8 @@ ios_extension(
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramApiFramework",
":SyncCoreFramework",
#":TelegramApiFramework",
#":SyncCoreFramework",
],
)
@ -1282,6 +1345,10 @@ plist_fragment(
<string>{telegram_bundle_id}</string>
<key>CFBundleName</key>
<string>Telegram</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
@ -1429,191 +1496,6 @@ plist_fragment(
)
)
plist_fragment(
name = "TelegramInfoIconsPlist",
extension = "plist",
template =
"""
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Black</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackIcon</string>
<string>BlackNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackClassicIcon</string>
<string>BlackClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>Blue</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueIcon</string>
<string>BlueNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueClassicIcon</string>
<string>BlueClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>WhiteFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>WhiteFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>IconDefault-60</string>
<string>IconDefault-76</string>
<string>IconDefault-83.5</string>
<string>IconDefault-Small-40</string>
<string>IconDefault-Small</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Black</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackIconIpad</string>
<string>BlackIconLargeIpad</string>
<string>BlackNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackClassicIconIpad</string>
<string>BlackClassicIconLargeIpad</string>
<string>BlackClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackFilledIconIpad</string>
<string>BlackFilledIconLargeIpad</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>Blue</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueIconIpad</string>
<string>BlueIconLargeIpad</string>
<string>BlueNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueClassicIconIpad</string>
<string>BlueClassicIconLargeIpad</string>
<string>BlueClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueFilledIconIpad</string>
<string>BlueFilledIconLargeIpad</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>WhiteFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>WhiteFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>IconDefault-60</string>
<string>IconDefault-76</string>
<string>IconDefault-83.5</string>
<string>IconDefault-Small-40</string>
<string>IconDefault-Small</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
""")
ios_application(
name = "Telegram",
bundle_id = "{telegram_bundle_id}".format(
@ -1626,21 +1508,18 @@ ios_application(
infoplists = [
":TelegramInfoPlist",
":AdditionalInfoPlist",
":TelegramInfoIconsPlist",
],
#app_icons = [
# ":DefaultAppIcon",
#],
ipa_post_processor = ":AddAlternateIcons",
resources = [
":LaunchScreen",
":DefaultAppIcon",
":AdditionalIcons",
#":DefaultAppIcon",
#":AppIcons",
],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramApiFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
":TelegramCoreFramework",
":AsyncDisplayKitFramework",
@ -1652,10 +1531,10 @@ ios_application(
],
extensions = [
":ShareExtension",
":WidgetExtension",
":NotificationContentExtension",
":NotificationServiceExtension",
":IntentsExtension",
#":WidgetExtension",
],
watch_application = ":TelegramWatchApp",
deps = [

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array/>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -102,7 +102,7 @@ dispatch_block_t fetchImage(BuildConfig *buildConfig, AccountProxyConnection * _
apiEnvironment.langPack = @"ios";
apiEnvironment.layer = @([serialization currentLayer]);
apiEnvironment.disableUpdates = true;
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:@"en"];
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:@""];
if (proxyConnection != nil) {
apiEnvironment = [apiEnvironment withUpdatedSocksProxySettings:[[MTSocksProxySettings alloc] initWithIp:proxyConnection.host port:(uint16_t)proxyConnection.port username:proxyConnection.username password:proxyConnection.password secret:proxyConnection.secret]];

View File

@ -3,7 +3,7 @@
@implementation Serialization
- (NSUInteger)currentLayer {
return 120;
return 122;
}
- (id _Nullable)parseMessage:(NSData * _Nullable)data {

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -56,7 +56,7 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
}
if !isMuted && hasUnread {
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: .combinedLocation)
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: .combinedLocation)
|> take(1)
|> map { view -> [INMessage] in
var messages: [INMessage] = []

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,16 @@
set -euo pipefail
ADD_PLIST="${0}.runfiles/__main__/Telegram/Telegram-iOS/AlternateIcons.plist"
ADD_PLIST_IPAD="${0}.runfiles/__main__/Telegram/Telegram-iOS/AlternateIcons-iPad.plist"
if [ -f "$1/Payload/Telegram.app/Info.plist" ]; then
INFO_PLIST="$1/Payload/Telegram.app/Info.plist"
else
INFO_PLIST="$1/Telegram.app/Info.plist"
fi
/usr/libexec/PlistBuddy -c "add :CFBundleIcons:CFBundleAlternateIcons dict" "$INFO_PLIST"
/usr/libexec/PlistBuddy -c "add :CFBundleIcons~ipad:CFBundleAlternateIcons dict" "$INFO_PLIST"
/usr/libexec/PlistBuddy -c "merge $ADD_PLIST :CFBundleIcons:CFBundleAlternateIcons" "$INFO_PLIST"
/usr/libexec/PlistBuddy -c "merge $ADD_PLIST_IPAD :CFBundleIcons~ipad:CFBundleAlternateIcons" "$INFO_PLIST"

View File

@ -0,0 +1,75 @@
<dict>
<key>Black</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackIconIpad</string>
<string>BlackIconLargeIpad</string>
<string>BlackNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackClassicIconIpad</string>
<string>BlackClassicIconLargeIpad</string>
<string>BlackClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackFilledIconIpad</string>
<string>BlackFilledIconLargeIpad</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>Blue</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueIconIpad</string>
<string>BlueIconLargeIpad</string>
<string>BlueNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueClassicIconIpad</string>
<string>BlueClassicIconLargeIpad</string>
<string>BlueClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueFilledIconIpad</string>
<string>BlueFilledIconLargeIpad</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>WhiteFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>WhiteFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>

View File

@ -0,0 +1,69 @@
<dict>
<key>Black</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackIcon</string>
<string>BlackNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackClassicIcon</string>
<string>BlackClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlackFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlackFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>Blue</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueIcon</string>
<string>BlueNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueClassic</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueClassicIcon</string>
<string>BlueClassicNotificationIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>BlueFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>BlueFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
<key>WhiteFilled</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>WhiteFilledIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
<string>CloudKit</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
<key>com.apple.developer.in-app-payments</key>
<array>
<string>merchant.ph.telegra.Telegraph</string>
<string>merchant.yandex.ph.telegra.Telegraph</string>
<string>merchant.sberbank.ph.telegra.Telegraph</string>
<string>merchant.sberbank.test.ph.telegra.Telegraph</string>
<string>merchant.privatbank.test.telergramios</string>
<string>merchant.privatbank.prod.telergram</string>
<string>merchant.telegram.tranzzo.test</string>
</array>
<key>com.apple.developer.pushkit.unrestricted-voip</key>
<true/>
</dict>
</plist>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Fork</string>
</array>
</dict>
</plist>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>X834Q8SBVP.org.telegram.Telegram-iOS</string>
</array>
<key>com.apple.developer.pushkit.unrestricted-voip</key>
<true/>
</dict>
</plist>

View File

@ -1974,6 +1974,7 @@
"Conversation.PinMessageAlertGroup" = "Pin this message and notify all members of the group?";
"Conversation.PinMessageAlert.OnlyPin" = "Only Pin";
"Conversation.PinMessageAlert.PinAndNotifyMembers" = "Pin and notify all members";
"Conversation.UnpinMessageAlert" = "Would you like to unpin this message?";
@ -2277,6 +2278,19 @@ Unused sets are archived when you add more.";
"Call.Minutes_any" = "%@ minutes";
"Call.Minutes_many" = "%@ minutes";
"Call.Minutes_0" = "%@ minutes";
"Call.Hours_1" = "%@ hour";
"Call.Hours_2" = "%@ hours";
"Call.Hours_3_10" = "%@ hours";
"Call.Hours_any" = "%@ hours";
"Call.Hours_many" = "%@ hours";
"Call.Hours_0" = "%@ hours";
"Call.Days_1" = "%@ day";
"Call.Days_2" = "%@ days";
"Call.Days_3_10" = "%@ days";
"Call.Days_any" = "%@ days";
"Call.Days_many" = "%@ days";
"Call.Days_0" = "%@ days";
"Call.ShortSeconds_1" = "%@ sec";
"Call.ShortSeconds_2" = "%@ sec";
@ -2611,6 +2625,7 @@ Unused sets are archived when you add more.";
"Channel.AdminLog.CanAddAdmins" = "Add New Admins";
"Channel.AdminLog.CanBeAnonymous" = "Remain Anonymous";
"Channel.AdminLog.CanEditMessages" = "Edit Messages";
"Channel.AdminLog.CanManageCalls" = "Manage Calls";
"Channel.AdminLog.MessageToggleInvitesOn" = "%@ enabled group invites";
"Channel.AdminLog.MessageToggleInvitesOff" = "%@ disabled group invites";
@ -5889,4 +5904,71 @@ Sorry for the inconvenience.";
"Stats.Message.PublicShares" = "Public Shares";
"Stats.Message.PrivateShares" = "Private Shares";
"ChatSettings.WidgetSettings" = "Widget";
"Conversation.EditingPhotoPanelTitle" = "Edit Photo";
"Conversation.TextCopied" = "Text copied to clipboard";
"Media.LimitedAccessTitle" = "Limited Access to Media";
"Media.LimitedAccessText" = "You've given Telegram access only to select number of photos.";
"Media.LimitedAccessManage" = "Manage";
"VoiceChat.BackTitle" = "Chat";
"VoiceChat.StatusSpeaking" = "speaking";
"VoiceChat.StatusListening" = "listening";
"VoiceChat.Connecting" = "Connecting...";
"VoiceChat.Reconnecting" = "Reconnecting...";
"VoiceChat.Unmute" = "Unmute";
"VoiceChat.UnmuteHelp" = "or hold and speak";
"VoiceChat.Live" = "You're Live";
"VoiceChat.Mute" = "Tap to Mute";
"VoiceChat.Muted" = "Muted";
"VoiceChat.MutedHelp" = "You are in Listen Only mode";
"VoiceChat.Audio" = "audio";
"VoiceChat.Leave" = "leave";
"VoiceChat.SpeakPermissionEveryone" = "All Members Can Speak";
"VoiceChat.SpeakPermissionAdmin" = "Only Admins Can Speak";
"VoiceChat.Share" = "Share Invite Link";
"VoiceChat.EndVoiceChat" = "End Voice Chat";
"VoiceChat.CopyInviteLink" = "Copy Invite Link";
"VoiceChat.UnmutePeer" = "Allow to Speak";
"VoiceChat.MutePeer" = "Mute";
"VoiceChat.InvitePeer" = "Invite";
"VoiceChat.RemovePeer" = "Remove";
"VoiceChat.RemovePeerConfirmation" = "Are you sure you want to remove %@ from the group chat?";
"VoiceChat.RemovePeerRemove" = "Remove";
"VoiceChat.PanelJoin" = "Join";
"VoiceChat.Title" = "Voice Chat";
"VoiceChat.UserInvited" = "You invited **%@** to the voice chat";
"Notification.VoiceChatInvitation" = "%1$@ invited %2$@ to the voice chat";
"Notification.VoiceChatInvitationForYou" = "%1$@ invited you to the voice chat";
"Notification.VoiceChatStarted" = "Voice chat started";
"Notification.VoiceChatEnded" = "Voice chat ended (%@)";
"VoiceChat.Panel.TapToJoin" = "Tap to join";
"VoiceChat.Panel.Members_0" = "%@ members";
"VoiceChat.Panel.Members_1" = "%@ member";
"VoiceChat.Panel.Members_2" = "%@ members";
"VoiceChat.Panel.Members_3_10" = "%@ members";
"VoiceChat.Panel.Members_many" = "%@ members";
"VoiceChat.Panel.Members_any" = "%@ members";
"VoiceChat.Panel.MembersSpeaking_0" = "%@ members speaking";
"VoiceChat.Panel.MembersSpeaking_1" = "%@ member speaking";
"VoiceChat.Panel.MembersSpeaking_2" = "%@ members speaking";
"VoiceChat.Panel.MembersSpeaking_3_10" = "%@ members speaking";
"VoiceChat.Panel.MembersSpeaking_many" = "%@ members speaking";
"VoiceChat.Panel.MembersSpeaking_any" = "%@ members speaking";
"ChannelInfo.CreateVoiceChat" = "Create Voice Chat";

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.TelegramHD</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.ph.telegra.Telegraph</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.fork.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.telegram.Telegram-iOS</string>
</array>
</dict>
</plist>

View File

@ -52,43 +52,98 @@ extension PeersWidgetData {
static let previewData = PeersWidgetData.placeholder
}
struct AvatarItemView: View {
var accountPeerId: Int64
var peer: WidgetDataPeer
var itemSize: CGFloat
var body: some View {
return ZStack {
Image(uiImage: avatarImage(accountPeerId: accountPeerId, peer: peer, size: CGSize(width: itemSize, height: itemSize)))
if let badge = peer.badge, badge.count > 0 {
Text("\(badge.count)")
.font(Font.system(size: 16.0))
.multilineTextAlignment(.center)
.foregroundColor(.white)
.padding(.horizontal, 4.0)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(badge.isMuted ? Color.gray : Color.red)
.frame(minWidth: 20, idealWidth: 20, maxWidth: .infinity, minHeight: 20, idealHeight: 20, maxHeight: 20.0, alignment: .center)
)
.position(x: floor(0.84 * itemSize), y: floor(0.16 * itemSize))
}
}
}
}
struct WidgetView: View {
@Environment(\.widgetFamily) private var widgetFamily
let data: PeersWidgetData
func placeholder(geometry: GeometryProxy) -> some View {
let defaultItemSize: CGFloat = 60.0
let defaultPaddingFraction: CGFloat = 0.36
let rowCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(rowCount) + defaultPaddingFraction * CGFloat(rowCount - 1)))
let columnCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(columnCount) + defaultPaddingFraction * CGFloat(columnCount - 1)))
let firstRowY = itemSize / 2.0
let secondRowY = itemSize / 2.0 + geometry.size.height - itemSize
return ZStack {
ForEach(0 ..< rowCount * 2, content: { i in
return Circle().frame(width: itemSize, height: itemSize).position(x: itemSize / 2.0 + floor(CGFloat(i % rowCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / rowCount == 0 ? firstRowY : secondRowY).foregroundColor(.gray)
ForEach(0 ..< columnCount * 2, content: { i in
return Circle().frame(width: itemSize, height: itemSize).position(x: itemSize / 2.0 + floor(CGFloat(i % columnCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / columnCount == 0 ? firstRowY : secondRowY).foregroundColor(.gray)
})
}
}
private func linkForPeer(id: Int64) -> String {
switch self.widgetFamily {
case .systemSmall:
return "\(buildConfig.appSpecificUrlScheme)://"
default:
return "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(id)"
}
}
func peersView(geometry: GeometryProxy, peers: WidgetDataPeers) -> some View {
let defaultItemSize: CGFloat = 60.0
let defaultPaddingFraction: CGFloat = 0.36
let rowCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(rowCount) + defaultPaddingFraction * CGFloat(rowCount - 1)))
let rowCount: Int
let rowHeight: CGFloat
let topOffset: CGFloat
switch self.widgetFamily {
case .systemLarge:
rowCount = 4
rowHeight = 88.0
topOffset = 12.0
default:
rowCount = 2
rowHeight = 76.0
topOffset = 0.0
}
let columnCount = Int(round(geometry.size.width / (defaultItemSize * (1.0 + defaultPaddingFraction))))
let itemSize = floor(geometry.size.width / (CGFloat(columnCount) + defaultPaddingFraction * CGFloat(columnCount - 1)))
let firstRowY = itemSize / 2.0
let secondRowY = itemSize / 2.0 + geometry.size.height - itemSize
let rowOffset: [CGFloat] = [
topOffset + itemSize / 2.0,
topOffset + itemSize / 2.0 + rowHeight,
topOffset + itemSize / 2.0 + rowHeight * 2,
topOffset + itemSize / 2.0 + rowHeight * 3,
]
return ZStack {
ForEach(0 ..< min(peers.peers.count, rowCount * 2), content: { i in
Link(destination: URL(string: "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(peers.peers[i].id)")!, label: {
Image(uiImage: avatarImage(accountPeerId: peers.accountPeerId, peer: peers.peers[i], size: CGSize(width: itemSize, height: itemSize)))
.frame(width: itemSize, height: itemSize)
ForEach(0 ..< min(peers.peers.count, columnCount * rowCount), content: { i in
Link(destination: URL(string: linkForPeer(id: peers.peers[i].id))!, label: {
AvatarItemView(
accountPeerId: peers.accountPeerId,
peer: peers.peers[i],
itemSize: itemSize
).frame(width: itemSize, height: itemSize)
}).frame(width: itemSize, height: itemSize)
.position(x: itemSize / 2.0 + floor(CGFloat(i % rowCount) * itemSize * (1.0 + defaultPaddingFraction)), y: i / rowCount == 0 ? firstRowY : secondRowY)
.position(x: itemSize / 2.0 + floor(CGFloat(i % columnCount) * itemSize * (1.0 + defaultPaddingFraction)), y: rowOffset[i / columnCount])
})
}
}
@ -123,7 +178,6 @@ struct WidgetView: View {
var body: some View {
ZStack {
Color(.systemBackground)
peerViews()
}
.padding(.all)
@ -214,7 +268,7 @@ struct Static_Widget: Widget {
WidgetView(data: getWidgetData())
}
)
.supportedFamilies([.systemMedium])
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
.configurationDisplayName(presentationData.widgetGalleryTitle)
.description(presentationData.widgetGalleryDescription)
}

View File

@ -31,9 +31,6 @@ ifneq ($(BUCK_DIR_CACHE),)
endif
check_env:
ifndef BUCK
$(error BUCK is not set)
endif
sh check_env.sh
kill_xcode:

View File

@ -1,4 +1,4 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
http_archive(
name = "com_google_protobuf",
@ -50,3 +50,9 @@ apple_support_dependencies()
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
http_file(
name = "cmake_tar_gz",
urls = ["https://github.com/Kitware/CMake/releases/download/v3.18.4/cmake-3.18.4-Darwin-x86_64.tar.gz"],
sha256 = "9d27049660474cf134ab46fa0e0db771b263313fcb8ba82ee8b2d1a1a62f8f20",
)

View File

@ -1,53 +0,0 @@
APP_VERSION="1.0"
CORE_COUNT=$(shell sysctl -n hw.logicalcpu)
CORE_COUNT_MINUS_ONE=$(shell expr ${CORE_COUNT} \- 1)
BAZEL=$(shell which bazel)
ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_CACHE_FLAGS=\
--disk_cache="${BAZEL_CACHE_DIR}"
endif
BAZEL_COMMON_FLAGS=\
--announce_rc \
--features=swift.use_global_module_cache \
BAZEL_DEBUG_FLAGS=\
--features=swift.enable_batch_mode \
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
BAZEL_OPT_FLAGS=\
--swiftcopt=-whole-module-optimization \
--swiftcopt='-num-threads' --swiftcopt='16' \
kill_xcode:
killall Xcode || true
wallet_app_debug_arm64:
WALLET_APP_VERSION="${APP_VERSION}" \
build-system/prepare-build.sh Wallet distribution
"${BAZEL}" build Wallet/Wallet ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} \
-c dbg \
--ios_multi_cpus=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
wallet_app:
WALLET_APP_VERSION="${APP_VERSION}" \
build-system/prepare-build.sh Wallet distribution
"${BAZEL}" build Wallet/Wallet ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7,arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
bazel_wallet_prepare_development_build:
WALLET_APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/prepare-build.sh Wallet development
wallet_project: kill_xcode bazel_wallet_prepare_development_build
WALLET_APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/generate-xcode-project.sh Wallet

View File

@ -1,136 +0,0 @@
load("//Config:utils.bzl",
"library_configs",
)
load("//Config:wallet_configs.bzl",
"app_binary_configs",
"app_info_plist_substitutions",
)
load("//Config:buck_rule_macros.bzl",
"framework_binary_dependencies",
"framework_bundle_dependencies",
)
framework_dependencies = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
]
resource_dependencies = [
"//submodules/WalletUI:WalletUIResources",
"//submodules/WalletUI:WalletUIAssets",
"//submodules/OverlayStatusController:OverlayStatusControllerResources",
":StringResources",
":InfoPlistStringResources",
":Icons",
":LaunchScreen",
]
apple_resource(
name = "StringResources",
files = [],
variants = glob([
"Strings/*.lproj/Localizable.strings",
]),
visibility = ["PUBLIC"],
)
apple_resource(
name = "InfoPlistStringResources",
files = [],
variants = glob([
"InfoPlistStrings/*.lproj/InfoPlist.strings",
]),
visibility = ["PUBLIC"],
)
apple_asset_catalog(
name = "Icons",
dirs = [
"Icons.xcassets",
],
app_icon = "AppIconWallet",
visibility = ["PUBLIC"],
)
apple_resource(
name = "LaunchScreen",
files = [
"LaunchScreen.xib",
],
visibility = ["PUBLIC"],
)
apple_library(
name = "AppLibrary",
visibility = [
"//Wallet:...",
],
configs = library_configs(),
swift_version = native.read_config("swift", "version"),
srcs = glob([
"Sources/**/*.m",
"Sources/**/*.swift",
]),
exported_linker_flags = [
"-lc++",
"-lz"
],
deps = [
"//submodules/WalletUI:WalletUI",
"//submodules/WalletCore:WalletCore",
"//submodules/BuildConfig:BuildConfig",
"//submodules/OverlayStatusController:OverlayStatusController",
]
+ framework_binary_dependencies(framework_dependencies),
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
"$SDKROOT/System/Library/Frameworks/VideoToolbox.framework",
"$SDKROOT/System/Library/Frameworks/AVFoundation.framework",
],
)
apple_binary(
name = "AppBinary",
visibility = [
"//Wallet:...",
],
configs = app_binary_configs(),
swift_version = native.read_config("swift", "version"),
srcs = [
"SupportFiles/Empty.swift",
],
deps = [
":AppLibrary",
]
+ resource_dependencies,
)
apple_bundle(
name = "Wallet",
visibility = [
"//:",
],
extension = "app",
binary = ":AppBinary",
product_name = "Wallet",
info_plist = "Info.plist",
info_plist_substitutions = app_info_plist_substitutions(),
deps = [
]
+ framework_bundle_dependencies(framework_dependencies),
)
apple_package(
name = "AppPackage",
bundle = ":Wallet",
)
xcode_workspace_config(
name = "workspace",
workspace_name = "WalletWorkspace",
src_target = ":Wallet",
)

View File

@ -1,189 +0,0 @@
load("@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
"ios_extension",
"ios_framework",
)
load("@build_bazel_rules_swift//swift:swift.bzl",
"swift_library",
)
load("//build-system/bazel-utils:plist_fragment.bzl",
"plist_fragment",
)
load(
"//build-input/data:variables.bzl",
"wallet_build_number",
"wallet_version",
"wallet_bundle_id",
"wallet_team_id",
)
config_setting(
name = "debug",
values = {
"compilation_mode": "dbg",
},
)
genrule(
name = "empty",
outs = ["empty.swift"],
cmd = "touch $(OUTS)",
)
swift_library(
name = "_LocalDebugOptions",
srcs = [":empty"],
copts = [
"-Xfrontend",
"-serialize-debugging-options",
],
deps = [
],
module_name = "_LocalDebugOptions",
tags = ["no-remote"],
visibility = ["//visibility:public"],
)
debug_deps = select({
":debug": [":_LocalDebugOptions"],
"//conditions:default": [],
})
plist_fragment(
name = "WalletInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleShortVersionString</key>
<string>{wallet_version}</string>
<key>CFBundleVersion</key>
<string>{wallet_build_number}</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>TON Wallet</string>
<key>CFBundleIdentifier</key>
<string>{wallet_bundle_id}</string>
<key>CFBundleName</key>
<string>TON Wallet</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>Please allow TON Wallet access to your camera for scanning QR codes.</string>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Please allow TON Wallet access to your Photo Stream in case you need to scan a QR code from a picture.</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIFileSharingEnabled</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIRequiresPersistentWiFi</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIViewEdgeAntialiasing</key>
<false/>
<key>UIViewGroupOpacity</key>
<false/>
""".format(
wallet_version = wallet_version,
wallet_build_number = wallet_build_number,
wallet_bundle_id = wallet_bundle_id,
)
)
filegroup(
name = "Strings",
srcs = glob([
"Strings/**/*",
], exclude = ["Strings/**/.*"]),
)
filegroup(
name = "Icons",
srcs = glob([
"Icons.xcassets/**/*",
], exclude = ["Icons.xcassets/**/.*"]),
)
objc_library(
name = "Main",
srcs = [
"Sources/main.m"
],
)
swift_library(
name = "Lib",
srcs = glob([
"Sources/**/*.swift",
]),
data = [
],
deps = [
"//submodules/WalletUI:WalletUI",
"//submodules/WalletCore:WalletCore",
"//submodules/BuildConfig:BuildConfig",
"//submodules/OverlayStatusController:OverlayStatusController",
],
)
ios_application(
name = "Wallet",
bundle_id = wallet_bundle_id,
families = ["iphone", "ipad"],
minimum_os_version = "9.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Wallet.mobileprovision",
infoplists = [
":WalletInfoPlist.plist",
],
app_icons = [
":Icons",
],
launch_storyboard = "LaunchScreen.xib",
strings = [
":Strings",
],
deps = [
":Main",
":Lib",
],
)

View File

@ -1,119 +0,0 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "GramIcon@40x40.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "GramIcon@60x60.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "GramIcon@58x58.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "GramIcon@87x87.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "GramIcon@80x80.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "GramIcon@120x120.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "GramIcon@120x120-1.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "GramIcon@180x180.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "GramIcon@20x20.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "GramIcon@40x40-1.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "GramIcon@29x29.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "GramIcon@58x58-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "GramIcon@40x40-2.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "GramIcon@80x80-1.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "GramIcon@76x76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "GramIcon@152x152.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "GramIcon@167x167.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "GramIcon-iTunesArtwork.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"pre-rendered" : true
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -1,97 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconName</key>
<string>AppIconWallet</string>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconName</key>
<string>AppIconWallet</string>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(PRODUCT_BUNDLE_SHORT_VERSION)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>Please allow TON Wallet access to your camera for scanning QR codes.</string>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Please allow TON Wallet access to your Photo Stream in case you need to scan a QR code from a picture.</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIFileSharingEnabled</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIRequiresPersistentWiFi</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIViewEdgeAntialiasing</key>
<false/>
<key>UIViewGroupOpacity</key>
<false/>
</dict>
</plist>

View File

@ -1,5 +0,0 @@
/* Localized versions of Info.plist keys */
"NSCameraUsageDescription" = "Please allow TON Wallet access to your camera for scanning QR codes.";
"NSPhotoLibraryUsageDescription" = "Please allow TON Wallet access to your Photo Stream in case you need to scan a QR code from a picture.";
"NSFaceIDUsageDescription" = "For better security, please allow TON Wallet to use your Face ID to authenticate payments.";

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15508"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<navigationController id="sSF-ws-R8Z">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translucent="NO" id="d5X-cy-bFB">
<rect key="frame" x="0.0" y="-44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="barTintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</navigationBar>
<viewControllers>
<viewController id="nui-yY-Mdn">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="YeQ-mV-ElX"/>
<viewControllerLayoutGuide type="bottom" id="n8M-Ll-9gB"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="iG4-qM-jMr">
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SrD-xF-5G3">
<rect key="frame" x="0.0" y="0.0" width="414" height="260"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Wallet/SplashCornerL" translatesAutoresizingMaskIntoConstraints="NO" id="4bZ-PB-VJX">
<rect key="frame" x="0.0" y="260" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Wallet/SplashCornerR" translatesAutoresizingMaskIntoConstraints="NO" id="K7L-Vs-8lO">
<rect key="frame" x="404" y="260" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
</view>
<navigationItem key="navigationItem" id="riQ-lf-mYe"/>
</viewController>
</viewControllers>
<point key="canvasLocation" x="-137.68115942028987" y="-95.089285714285708"/>
</navigationController>
</objects>
<resources>
<image name="Wallet/SplashCornerL" width="10" height="10"/>
<image name="Wallet/SplashCornerR" width="10" height="10"/>
</resources>
</document>

View File

@ -1,27 +0,0 @@
# Test Gram Wallet (iOS)
This is the source code and build instructions for a TON Testnet Wallet implementation for iOS.
1. Install Xcode 11.4
```
https://apps.apple.com/app/xcode/id497799835
```
Make sure to launch Xcode at least once and set up command-line tools paths (Xcode — Preferences — Locations — Command Line Tools)
2. Build the app (IPA)
Note:
It is recommended to use an artifact cache to optimize build speed. Prepend any of the following commands with
```
BAZEL_CACHE_DIR="path/to/existing/directory"
```
```
sh wallet_env.sh make wallet_app
```
3. If needed, generate Xcode project
```
sh wallet_env.sh make wallet_project
```

View File

@ -1,848 +0,0 @@
import UIKit
import Display
import OverlayStatusController
import SwiftSignalKit
import BuildConfig
import WalletUI
import WalletCore
import AVFoundation
private func encodeText(_ string: String, _ key: Int) -> String {
var result = ""
for c in string.unicodeScalars {
result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!))
}
return result
}
private let statusBarRootViewClass: AnyClass = NSClassFromString("UIStatusBar")!
private let statusBarPlaceholderClass: AnyClass? = NSClassFromString("UIStatusBar_Placeholder")
private let cutoutStatusBarForegroundClass: AnyClass? = NSClassFromString("_UIStatusBar")
private let keyboardViewClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuIptuWjfx", -1))!
private let keyboardViewContainerClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuDpoubjofsWjfx", -1))!
private let keyboardWindowClass: AnyClass? = {
if #available(iOS 9.0, *) {
return NSClassFromString(encodeText("VJSfnpufLfzcpbseXjoepx", -1))
} else {
return NSClassFromString(encodeText("VJUfyuFggfdutXjoepx", -1))
}
}()
private class ApplicationStatusBarHost: StatusBarHost {
private let application = UIApplication.shared
var isApplicationInForeground: Bool {
switch self.application.applicationState {
case .background:
return false
default:
return true
}
}
var statusBarFrame: CGRect {
return self.application.statusBarFrame
}
var statusBarStyle: UIStatusBarStyle {
get {
return self.application.statusBarStyle
} set(value) {
self.setStatusBarStyle(value, animated: false)
}
}
func setStatusBarStyle(_ style: UIStatusBarStyle, animated: Bool) {
self.application.setStatusBarStyle(style, animated: animated)
}
func setStatusBarHidden(_ value: Bool, animated: Bool) {
self.application.setStatusBarHidden(value, with: animated ? .fade : .none)
}
var statusBarWindow: UIView? {
return self.application.value(forKey: "statusBarWindow") as? UIView
}
var statusBarView: UIView? {
guard let containerView = self.statusBarWindow?.subviews.first else {
return nil
}
if containerView.isKind(of: statusBarRootViewClass) {
return containerView
}
if let statusBarPlaceholderClass = statusBarPlaceholderClass {
if containerView.isKind(of: statusBarPlaceholderClass) {
return containerView
}
}
for subview in containerView.subviews {
if let cutoutStatusBarForegroundClass = cutoutStatusBarForegroundClass, subview.isKind(of: cutoutStatusBarForegroundClass) {
return subview
}
}
return nil
}
var keyboardWindow: UIWindow? {
guard let keyboardWindowClass = keyboardWindowClass else {
return nil
}
for window in UIApplication.shared.windows {
if window.isKind(of: keyboardWindowClass) {
return window
}
}
return nil
}
var keyboardView: UIView? {
guard let keyboardWindow = self.keyboardWindow, let keyboardViewContainerClass = keyboardViewContainerClass, let keyboardViewClass = keyboardViewClass else {
return nil
}
for view in keyboardWindow.subviews {
if view.isKind(of: keyboardViewContainerClass) {
for subview in view.subviews {
if subview.isKind(of: keyboardViewClass) {
return subview
}
}
}
}
return nil
}
var handleVolumeControl: Signal<Bool, NoError> {
return .single(false)
}
}
private final class FileBackedStorageImpl {
private let queue: Queue
private let path: String
private var data: Data?
private var subscribers = Bag<(Data?) -> Void>()
init(queue: Queue, path: String) {
self.queue = queue
self.path = path
}
func get() -> Data? {
if let data = self.data {
return data
} else {
self.data = try? Data(contentsOf: URL(fileURLWithPath: self.path))
return self.data
}
}
func set(data: Data) {
self.data = data
do {
try data.write(to: URL(fileURLWithPath: self.path), options: .atomic)
} catch let error {
print("Error writng data: \(error)")
}
for f in self.subscribers.copyItems() {
f(data)
}
}
func watch(_ f: @escaping (Data?) -> Void) -> Disposable {
f(self.get())
let index = self.subscribers.add(f)
let queue = self.queue
return ActionDisposable { [weak self] in
queue.async {
guard let strongSelf = self else {
return
}
strongSelf.subscribers.remove(index)
}
}
}
}
private final class FileBackedStorage {
private let queue = Queue()
private let impl: QueueLocalObject<FileBackedStorageImpl>
init(path: String) {
let queue = self.queue
self.impl = QueueLocalObject(queue: queue, generate: {
return FileBackedStorageImpl(queue: queue, path: path)
})
}
func get() -> Signal<Data?, NoError> {
return Signal { subscriber in
self.impl.with { impl in
subscriber.putNext(impl.get())
subscriber.putCompletion()
}
return EmptyDisposable
}
}
func set(data: Data) -> Signal<Never, NoError> {
return Signal { subscriber in
self.impl.with { impl in
impl.set(data: data)
subscriber.putCompletion()
}
return EmptyDisposable
}
}
func update<T>(_ f: @escaping (Data?) -> (Data, T)) -> Signal<T, NoError> {
return Signal { subscriber in
self.impl.with { impl in
let (data, result) = f(impl.get())
impl.set(data: data)
subscriber.putNext(result)
subscriber.putCompletion()
}
return EmptyDisposable
}
}
func watch() -> Signal<Data?, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.watch({ data in
subscriber.putNext(data)
}))
}
return disposable
}
}
}
private let records = Atomic<[WalletStateRecord]>(value: [])
private final class WalletStorageInterfaceImpl: WalletStorageInterface {
private let storage: FileBackedStorage
private let configurationStorage: FileBackedStorage
init(path: String, configurationPath: String) {
self.storage = FileBackedStorage(path: path)
self.configurationStorage = FileBackedStorage(path: configurationPath)
}
func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> {
return self.storage.watch()
|> map { data -> [WalletStateRecord] in
guard let data = data else {
return []
}
do {
return try JSONDecoder().decode(Array<WalletStateRecord>.self, from: data)
} catch let error {
print("Error deserializing data: \(error)")
return []
}
}
}
func getWalletRecords() -> Signal<[WalletStateRecord], NoError> {
return self.storage.get()
|> map { data -> [WalletStateRecord] in
guard let data = data else {
return []
}
do {
return try JSONDecoder().decode(Array<WalletStateRecord>.self, from: data)
} catch let error {
print("Error deserializing data: \(error)")
return []
}
}
}
func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> {
return self.storage.update { data -> (Data, [WalletStateRecord]) in
let records: [WalletStateRecord] = data.flatMap {
try? JSONDecoder().decode(Array<WalletStateRecord>.self, from: $0)
} ?? []
let updatedRecords = f(records)
do {
let updatedData = try JSONEncoder().encode(updatedRecords)
return (updatedData, updatedRecords)
} catch let error {
print("Error serializing data: \(error)")
return (Data(), updatedRecords)
}
}
}
func mergedLocalWalletConfiguration() -> Signal<MergedLocalWalletConfiguration, NoError> {
return self.configurationStorage.watch()
|> map { data -> MergedLocalWalletConfiguration in
guard let data = data, !data.isEmpty else {
return .default
}
do {
return try JSONDecoder().decode(MergedLocalWalletConfiguration.self, from: data)
} catch let error {
print("Error deserializing data: \(error)")
return .default
}
}
}
func localWalletConfiguration() -> Signal<LocalWalletConfiguration, NoError> {
return self.mergedLocalWalletConfiguration()
|> mapToSignal { value -> Signal<LocalWalletConfiguration, NoError> in
return .single(value.configuration)
}
|> distinctUntilChanged
}
func updateMergedLocalWalletConfiguration(_ f: @escaping (MergedLocalWalletConfiguration) -> MergedLocalWalletConfiguration) -> Signal<Never, NoError> {
return self.configurationStorage.update { data -> (Data, Void) in
do {
let current: MergedLocalWalletConfiguration?
if let data = data, !data.isEmpty {
current = try? JSONDecoder().decode(MergedLocalWalletConfiguration.self, from: data)
} else {
current = nil
}
let updated = f(current ?? .default)
let updatedData = try JSONEncoder().encode(updated)
return (updatedData, Void())
} catch let error {
print("Error serializing data: \(error)")
return (Data(), Void())
}
}
|> ignoreValues
}
func updateLocalWalletConfiguration(_ f: @escaping (LocalWalletConfiguration) -> LocalWalletConfiguration) -> Signal<Never, NoError> {
return self.updateMergedLocalWalletConfiguration { value in
var value = value
value.configuration = f(value.configuration)
return value
}
}
}
private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var storage: WalletStorageInterface {
return self.storageImpl
}
private let storageImpl: WalletStorageInterfaceImpl
let tonInstance: TonInstance
let keychain: TonKeychain
let presentationData: WalletPresentationData
let window: Window1
let supportsCustomConfigurations: Bool = true
let termsUrl: String? = nil
let feeInfoUrl: String? = nil
private var currentImagePickerCompletion: ((UIImage) -> Void)?
var inForeground: Signal<Bool, NoError> {
return .single(true)
}
func getServerSalt() -> Signal<Data, WalletContextGetServerSaltError> {
return .single(Data())
}
func downloadFile(url: URL) -> Signal<Data, WalletDownloadFileError> {
return download(url: url)
|> mapError { _ in
return .generic
}
}
func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal<Never, NoError> {
return self.storageImpl.updateMergedLocalWalletConfiguration { configuration in
var configuration = configuration
configuration.configuration.source = source
configuration.configuration.blockchainName = blockchainName
configuration.resolved = ResolvedLocalWalletConfiguration(source: source, value: resolvedValue)
return configuration
}
}
func presentNativeController(_ controller: UIViewController) {
self.window.presentNative(controller)
}
func idleTimerExtension() -> Disposable {
return EmptyDisposable
}
func openUrl(_ url: String) {
if let parsedUrl = URL(string: url) {
UIApplication.shared.openURL(parsedUrl)
}
}
func shareUrl(_ url: String) {
if let parsedUrl = URL(string: url) {
self.presentNativeController(UIActivityViewController(activityItems: [parsedUrl], applicationActivities: nil))
}
}
func openPlatformSettings() {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.openURL(url)
}
}
func authorizeAccessToCamera(completion: @escaping () -> Void) {
AVCaptureDevice.requestAccess(for: AVMediaType.video) { [weak self] response in
Queue.mainQueue().async {
guard let strongSelf = self else {
return
}
if response {
completion()
} else {
let presentationData = strongSelf.presentationData
let controller = standardTextAlertController(theme: presentationData.theme.alert, title: presentationData.strings.Wallet_AccessDenied_Title, text: presentationData.strings.Wallet_AccessDenied_Camera, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Wallet_Intro_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Wallet_AccessDenied_Settings, action: {
strongSelf.openPlatformSettings()
})])
strongSelf.window.present(controller, on: .root)
}
}
}
}
func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void) {
self.currentImagePickerCompletion = completion
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = false
pickerController.mediaTypes = ["public.image"]
pickerController.sourceType = .photoLibrary
self.presentNativeController(pickerController)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let currentImagePickerCompletion = self.currentImagePickerCompletion
self.currentImagePickerCompletion = nil
if let image = info[.editedImage] as? UIImage {
currentImagePickerCompletion?(image)
} else if let image = info[.originalImage] as? UIImage {
currentImagePickerCompletion?(image)
}
picker.presentingViewController?.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.currentImagePickerCompletion = nil
picker.presentingViewController?.dismiss(animated: true, completion: nil)
}
init(basePath: String, storage: WalletStorageInterfaceImpl, config: String, blockchainName: String, presentationData: WalletPresentationData, navigationBarTheme: NavigationBarTheme, window: Window1) {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: basePath + "/keys"), withIntermediateDirectories: true, attributes: nil)
self.storageImpl = storage
self.window = window
self.tonInstance = TonInstance(
basePath: basePath + "/keys",
config: config,
blockchainName: blockchainName,
proxy: nil
)
let baseAppBundleId = Bundle.main.bundleIdentifier!
#if targetEnvironment(simulator)
self.keychain = TonKeychain(encryptionPublicKey: {
return .single(Data())
}, encrypt: { data in
return .single(TonKeychainEncryptedData(publicKey: Data(), data: data))
}, decrypt: { data in
return .single(data.data)
})
#else
self.keychain = TonKeychain(encryptionPublicKey: {
return Signal { subscriber in
BuildConfig.getHardwareEncryptionAvailable(withBaseAppBundleId: baseAppBundleId, completion: { value in
subscriber.putNext(value)
subscriber.putCompletion()
})
return EmptyDisposable
}
}, encrypt: { data in
return Signal { subscriber in
BuildConfig.encryptApplicationSecret(data, baseAppBundleId: baseAppBundleId, completion: { result, publicKey in
if let result = result, let publicKey = publicKey {
subscriber.putNext(TonKeychainEncryptedData(publicKey: publicKey, data: result))
subscriber.putCompletion()
} else {
subscriber.putError(.generic)
}
})
return EmptyDisposable
}
}, decrypt: { encryptedData in
return Signal { subscriber in
BuildConfig.decryptApplicationSecret(encryptedData.data, publicKey: encryptedData.publicKey, baseAppBundleId: baseAppBundleId, completion: { result, cancelled in
if let result = result {
subscriber.putNext(result)
} else {
let error: TonKeychainDecryptDataError
if cancelled {
error = .cancelled
} else {
error = .generic
}
subscriber.putError(error)
}
subscriber.putCompletion()
})
return EmptyDisposable
}
})
#endif
self.presentationData = presentationData
super.init()
}
}
@objc(AppDelegate)
final class AppDelegate: NSObject, UIApplicationDelegate {
var window: UIWindow?
private var mainWindow: Window1?
private var walletContext: WalletContextImpl?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let statusBarHost = ApplicationStatusBarHost()
let (window, hostView) = nativeWindowHostView()
let mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
self.mainWindow = mainWindow
hostView.containerView.backgroundColor = UIColor.white
self.window = window
let accentColor = UIColor(rgb: 0x007ee5)
let navigationBarTheme = NavigationBarTheme(
buttonColor: accentColor,
disabledButtonColor: UIColor(rgb: 0xd0d0d0),
primaryTextColor: .black,
backgroundColor: UIColor(rgb: 0xf7f7f7),
separatorColor: UIColor(rgb: 0xb1b1b1),
badgeBackgroundColor: UIColor(rgb: 0xff3b30),
badgeStrokeColor: UIColor(rgb: 0xff3b30),
badgeTextColor: .white
)
let presentationData = WalletPresentationData(
theme: WalletTheme(
info: WalletInfoTheme(
buttonBackgroundColor: UIColor(rgb: 0x32aafe),
buttonTextColor: .white,
incomingFundsTitleColor: UIColor(rgb: 0x00b12c),
outgoingFundsTitleColor: UIColor(rgb: 0xff3b30)
), transaction: WalletTransactionTheme(
descriptionBackgroundColor: UIColor(rgb: 0xf1f1f4),
descriptionTextColor: .black
), setup: WalletSetupTheme(
buttonFillColor: accentColor,
buttonForegroundColor: .white,
inputBackgroundColor: UIColor(rgb: 0xe9e9e9),
inputPlaceholderColor: UIColor(rgb: 0x818086),
inputTextColor: .black,
inputClearButtonColor: UIColor(rgb: 0x7b7b81).withAlphaComponent(0.8)
),
list: WalletListTheme(
itemPrimaryTextColor: .black,
itemSecondaryTextColor: UIColor(rgb: 0x8e8e93),
itemPlaceholderTextColor: UIColor(rgb: 0xc8c8ce),
itemDestructiveColor: UIColor(rgb: 0xff3b30),
itemAccentColor: accentColor,
itemDisabledTextColor: UIColor(rgb: 0x8e8e93),
plainBackgroundColor: .white,
blocksBackgroundColor: UIColor(rgb: 0xefeff4),
itemPlainSeparatorColor: UIColor(rgb: 0xc8c7cc),
itemBlocksBackgroundColor: .white,
itemBlocksSeparatorColor: UIColor(rgb: 0xc8c7cc),
itemHighlightedBackgroundColor: UIColor(rgb: 0xe5e5ea),
sectionHeaderTextColor: UIColor(rgb: 0x6d6d72),
freeTextColor: UIColor(rgb: 0x6d6d72),
freeTextErrorColor: UIColor(rgb: 0xcf3030),
inputClearButtonColor: UIColor(rgb: 0xcccccc)
),
statusBarStyle: .Black,
navigationBar: navigationBarTheme,
keyboardAppearance: .light,
alert: AlertControllerTheme(
backgroundType: .light,
backgroundColor: .white,
separatorColor: UIColor(white: 0.9, alpha: 1.0),
highlightedItemColor: UIColor(rgb: 0xe5e5ea),
primaryColor: .black,
secondaryColor: UIColor(rgb: 0x5e5e5e),
accentColor: accentColor,
destructiveColor: UIColor(rgb: 0xff3b30),
disabledColor: UIColor(rgb: 0xd0d0d0),
baseFontSize: 17.0
),
actionSheet: ActionSheetControllerTheme(
dimColor: UIColor(white: 0.0, alpha: 0.4),
backgroundType: .light,
itemBackgroundColor: .white,
itemHighlightedBackgroundColor: UIColor(white: 0.9, alpha: 1.0),
standardActionTextColor: accentColor,
destructiveActionTextColor: UIColor(rgb: 0xff3b30),
disabledActionTextColor: UIColor(rgb: 0xb3b3b3),
primaryTextColor: .black,
secondaryTextColor: UIColor(rgb: 0x5e5e5e),
controlAccentColor: accentColor,
controlColor: UIColor(rgb: 0x7e8791),
switchFrameColor: UIColor(rgb: 0xe0e0e0),
switchContentColor: UIColor(rgb: 0x77d572),
switchHandleColor: UIColor(rgb: 0xffffff),
baseFontSize: 17.0
)
), strings: WalletStrings(
primaryComponent: WalletStringsComponent(
languageCode: "en",
localizedName: "English",
pluralizationRulesCode: "en",
dict: [:]
),
secondaryComponent: nil,
groupingSeparator: " "
), dateTimeFormat: WalletPresentationDateTimeFormat(
timeFormat: .regular,
dateFormat: .dayFirst,
dateSeparator: ".",
decimalSeparator: ".",
groupingSeparator: " "
)
)
let navigationController = NavigationController(
mode: .single,
theme: NavigationControllerTheme(
statusBar: .black,
navigationBar: navigationBarTheme,
emptyAreaColor: .white
), backgroundDetailsMode: nil
)
mainWindow.viewController = navigationController
navigationController.setViewControllers([WalletApplicationSplashScreen(theme: presentationData.theme)], animated: false)
self.window?.makeKeyAndVisible()
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
#if DEBUG
print("Starting with \(documentsPath)")
#endif
let storage = WalletStorageInterfaceImpl(path: documentsPath + "/data", configurationPath: documentsPath + "/configuration_v2")
let initialConfigValue = storage.mergedLocalWalletConfiguration()
|> take(1)
|> mapToSignal { configuration -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
if let resolved = configuration.resolved, resolved.source == configuration.configuration.source {
return .single((resolved, configuration.configuration.blockchainName))
} else {
return .complete()
}
}
let updatedConfigValue = storage.localWalletConfiguration()
|> mapToSignal { configuration -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
switch configuration.source {
case let .url(url):
guard let parsedUrl = URL(string: url) else {
return .complete()
}
return download(url: parsedUrl)
|> retry(1.0, maxDelay: 5.0, onQueue: .mainQueue())
|> mapToSignal { data -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
if let string = String(data: data, encoding: .utf8) {
return .single((ResolvedLocalWalletConfiguration(source: configuration.source, value: string), configuration.blockchainName))
} else {
return .complete()
}
}
case let .string(string):
return .single((ResolvedLocalWalletConfiguration(source: configuration.source, value: string), configuration.blockchainName))
}
}
|> distinctUntilChanged(isEqual: { lhs, rhs in
return lhs.0 == rhs.0 && lhs.1 == rhs.1
})
|> afterNext { (resolved, _) in
let _ = storage.updateMergedLocalWalletConfiguration({ current in
var current = current
current.resolved = resolved
return current
}).start()
}
let resolvedInitialConfig = (
initialConfigValue
|> then(updatedConfigValue)
)
|> take(1)
let _ = (resolvedInitialConfig
|> deliverOnMainQueue).start(next: { (initialResolvedConfig, initialConfigBlockchainName) in
let walletContext = WalletContextImpl(basePath: documentsPath, storage: storage, config: initialResolvedConfig.value, blockchainName: initialConfigBlockchainName, presentationData: presentationData, navigationBarTheme: navigationBarTheme, window: mainWindow)
self.walletContext = walletContext
let beginWithController: (ViewController) -> Void = { controller in
let begin: (Bool) -> Void = { animated in
navigationController.setViewControllers([controller], animated: false)
if animated {
navigationController.viewControllers.last?.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
}
var previousBlockchainName = initialConfigBlockchainName
let _ = (updatedConfigValue
|> deliverOnMainQueue).start(next: { resolved, blockchainName in
let _ = walletContext.tonInstance.validateConfig(config: resolved.value, blockchainName: blockchainName).start(error: { _ in
}, completed: {
let _ = walletContext.tonInstance.updateConfig(config: resolved.value, blockchainName: blockchainName).start()
if previousBlockchainName != blockchainName {
previousBlockchainName = blockchainName
let overlayController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
mainWindow.present(overlayController, on: .root)
let _ = (deleteAllLocalWalletsData(storage: walletContext.storage, tonInstance: walletContext.tonInstance)
|> deliverOnMainQueue).start(error: { [weak overlayController] _ in
overlayController?.dismiss()
}, completed: { [weak overlayController] in
overlayController?.dismiss()
navigationController.setViewControllers([WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)], animated: true)
})
}
})
})
}
if let splashScreen = navigationController.viewControllers.first as? WalletApplicationSplashScreen, let _ = controller as? WalletSplashScreen {
splashScreen.animateOut(completion: {
begin(true)
})
} else {
begin(false)
}
}
let _ = (combineLatest(queue: .mainQueue(),
walletContext.storage.getWalletRecords(),
walletContext.keychain.encryptionPublicKey()
)
|> deliverOnMainQueue).start(next: { records, publicKey in
if let record = records.first {
if let publicKey = publicKey {
let recordPublicKey: Data
switch record.info {
case let .ready(info, _, _):
recordPublicKey = info.encryptedSecret.publicKey
case let .imported(info):
recordPublicKey = info.encryptedSecret.publicKey
}
if recordPublicKey == publicKey {
switch record.info {
case let .ready(info, exportCompleted, _):
if exportCompleted {
let _ = (walletAddress(walletInfo: info, tonInstance: walletContext.tonInstance)
|> deliverOnMainQueue).start(next: { address in
let infoScreen = WalletInfoScreen(context: walletContext, walletInfo: info, address: address, enableDebugActions: false)
beginWithController(infoScreen)
})
} else {
let createdScreen = WalletSplashScreen(context: walletContext, mode: .created(walletInfo: info, words: nil), walletCreatedPreloadState: nil)
beginWithController(createdScreen)
}
case let .imported(info):
let createdScreen = WalletSplashScreen(context: walletContext, mode: .successfullyImported(importedInfo: info), walletCreatedPreloadState: nil)
beginWithController(createdScreen)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageReset(.changed), walletCreatedPreloadState: nil)
beginWithController(splashScreen)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: WalletSplashMode.secureStorageReset(.notAvailable), walletCreatedPreloadState: nil)
beginWithController(splashScreen)
}
} else {
if publicKey != nil {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
beginWithController(splashScreen)
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil)
beginWithController(splashScreen)
}
}
})
})
return true
}
}
private enum DownloadFileError {
case network
}
private func download(url: URL) -> Signal<Data, DownloadFileError> {
return Signal { subscriber in
let completed = Atomic<Bool>(value: false)
let downloadTask = URLSession.shared.downloadTask(with: url, completionHandler: { location, _, error in
let _ = completed.swap(true)
if let location = location, let data = try? Data(contentsOf: location) {
subscriber.putNext(data)
subscriber.putCompletion()
} else {
subscriber.putError(.network)
}
})
downloadTask.resume()
return ActionDisposable {
if !completed.with({ $0 }) {
downloadTask.cancel()
}
}
}
}
struct ResolvedLocalWalletConfiguration: Codable, Equatable {
var source: LocalWalletConfigurationSource
var value: String
}
struct MergedLocalWalletConfiguration: Codable, Equatable {
var configuration: LocalWalletConfiguration
var resolved: ResolvedLocalWalletConfiguration?
}
private extension MergedLocalWalletConfiguration {
static var `default`: MergedLocalWalletConfiguration {
return MergedLocalWalletConfiguration(configuration: LocalWalletConfiguration(source: .url("https://test.ton.org/config.json"), blockchainName: "testnet2"), resolved: nil)
}
}

View File

@ -1,5 +0,0 @@
import UIKit
@objc(Application) class Application: UIApplication {
}

View File

@ -1,7 +0,0 @@
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, @"Application", @"AppDelegate");
}
}

View File

@ -1,224 +0,0 @@
"Wallet.Updated.JustNow" = "updated just now";
"Wallet.Updated.MinutesAgo_0" = "%@ minutes ago"; //three to ten
"Wallet.Updated.MinutesAgo_1" = "1 minute ago"; //one
"Wallet.Updated.MinutesAgo_2" = "2 minutes ago"; //two
"Wallet.Updated.MinutesAgo_3_10" = "%@ minutes ago"; //three to ten
"Wallet.Updated.MinutesAgo_many" = "%@ minutes ago"; // more than ten
"Wallet.Updated.MinutesAgo_any" = "%@ minutes ago"; // more than ten
"Wallet.Updated.HoursAgo_0" = "%@ hours ago";
"Wallet.Updated.HoursAgo_1" = "1 hour ago";
"Wallet.Updated.HoursAgo_2" = "2 hours ago";
"Wallet.Updated.HoursAgo_3_10" = "%@ hours ago";
"Wallet.Updated.HoursAgo_any" = "%@ hours ago";
"Wallet.Updated.HoursAgo_many" = "%@ hours ago";
"Wallet.Updated.HoursAgo_0" = "%@ hours ago";
"Wallet.Updated.YesterdayAt" = "yesterday at %@";
"Wallet.Updated.AtDate" = "%@";
"Wallet.Updated.TodayAt" = "today at %@";
"Wallet.Info.WalletCreated" = "Wallet Created";
"Wallet.Info.Address" = "Your wallet address";
"Wallet.Info.YourBalance" = "your balance";
"Wallet.Info.Receive" = "Receive";
"Wallet.Info.ReceiveGrams" = "Receive Grams";
"Wallet.Info.Send" = "Send";
"Wallet.Info.RefreshErrorTitle" = "No network";
"Wallet.Info.RefreshErrorText" = "Couldn't refresh balance. Please make sure your internet connection is working and try again.";
"Wallet.Info.RefreshErrorNetworkText" = "Wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.UnknownTransaction" = "Empty Transaction";
"Wallet.Info.TransactionTo" = "to";
"Wallet.Info.TransactionFrom" = "from";
"Wallet.Info.Updating" = "updating";
"Wallet.Info.TransactionBlockchainFee" = "%@ blockchain fees";
"Wallet.Info.TransactionPendingHeader" = "Pending";
"Wallet.Qr.ScanCode" = "Scan QR Code";
"Wallet.Qr.Title" = "QR Code";
"Wallet.Receive.Title" = "Receive Grams";
"Wallet.Receive.AddressHeader" = "YOUR WALLET ADDRESS";
"Wallet.Receive.InvoiceUrlHeader" = "INVOICE URL";
"Wallet.Receive.CopyAddress" = "Copy Wallet Address";
"Wallet.Receive.CopyInvoiceUrl" = "Copy Invoice URL";
"Wallet.Receive.ShareAddress" = "Share Wallet Address";
"Wallet.Receive.ShareInvoiceUrl" = "Share Invoice URL";
"Wallet.Receive.ShareUrlInfo" = "Share this link with other Gram wallet owners to receive Grams from them. Note: this link won't work for real Grams.";
"Wallet.Receive.AmountHeader" = "AMOUNT";
"Wallet.Receive.AmountText" = "Grams to receive";
"Wallet.Receive.AmountInfo" = "You can specify the amount and purpose of the payment to save the sender some time.";
"Wallet.Receive.CommentHeader" = "COMMENT (OPTIONAL)";
"Wallet.Receive.CommentInfo" = "Description of the payment";
"Wallet.Receive.AddressCopied" = "Address copied to clipboard.";
"Wallet.Receive.InvoiceUrlCopied" = "Invoice URL copied to clipboard.";
"Wallet.Send.Title" = "Send Grams";
"Wallet.Send.AddressHeader" = "RECIPIENT WALLET ADDRESS";
"Wallet.Send.AddressText" = "Enter wallet address...";
"Wallet.Send.AddressInfo" = "Paste the 48-letter address of the recipient here or ask them to send you a ton:// link.";
"Wallet.Send.Balance" = "Balance: %@";
"Wallet.Send.AmountText" = "Grams to send";
"Wallet.Send.Confirmation" = "Confirmation";
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n\n%2$@?\n\nBlockchain fees: ~%3$@ grams";
"Wallet.Send.ConfirmationConfirm" = "Confirm";
"Wallet.Send.Send" = "Send";
"Wallet.Send.OwnAddressAlertTitle" = "Warning";
"Wallet.Send.OwnAddressAlertText" = "Sending Grams from a wallet to the same wallet doesn't make sense, you will simply waste a portion of the value on blockchain fees.";
"Wallet.Send.OwnAddressAlertProceed" = "Proceed";
"Wallet.Send.TransactionInProgress" = "Please wait until the current transaction is completed.";
"Wallet.Send.SyncInProgress" = "Please wait while the wallet finishes syncing with the TON Blockchain.";
"Wallet.Send.EncryptComment" = "Encrypt Text";
"Wallet.Settings.Title" = "Settings";
"Wallet.Settings.Configuration" = "Server Settings";
"Wallet.Settings.ConfigurationInfo" = "Advanced Settings";
"Wallet.Settings.BackupWallet" = "Backup Wallet";
"Wallet.Settings.DeleteWallet" = "Delete Wallet";
"Wallet.Settings.DeleteWalletInfo" = "This will disconnect the wallet from this app. You will be able to restore your wallet using 24 secret words or import another wallet.\n\nGram Wallets are located in the decentralized TON Blockchain. If you want a wallet to be deleted, simply transfer all the grams from it and leave it empty.";
"Wallet.Intro.NotNow" = "Not Now";
"Wallet.Intro.ImportExisting" = "Import existing wallet";
"Wallet.Intro.CreateErrorTitle" = "An Error Occurred";
"Wallet.Intro.CreateErrorText" = "Sorry. Please try again.";
"Wallet.Intro.Title" = "Gram Wallet";
"Wallet.Intro.Text" = "Gram wallet allows you to make fast and secure blockchain-based payments without intermediaries.";
"Wallet.Intro.CreateWallet" = "Create My Wallet";
"Wallet.Intro.Terms" = "By creating a wallet you accept the\n[Terms of Conditions]().";
"Wallet.Created.Title" = "Congratulations";
"Wallet.Created.Text" = "Your Gram wallet has just been created. Only you control it.\n\nTo be able to always have access to it, please write down your secret words and\nset up a secure passcode.";
"Wallet.Created.Proceed" = "Proceed";
"Wallet.Created.ExportErrorTitle" = "Error";
"Wallet.Created.ExportErrorText" = "Encryption error. Please make sure you have enabled a device passcode in iOS settings and try again.";
"Wallet.Completed.Title" = "Ready to go!";
"Wallet.Completed.Text" = "Youre all set. Now you have a wallet that only you control - directly, without middlemen or bankers.";
"Wallet.Completed.ViewWallet" = "View My Wallet";
"Wallet.RestoreFailed.Title" = "Too Bad";
"Wallet.RestoreFailed.Text" = "Without the secret words, you can't\nrestore access to your wallet.";
"Wallet.RestoreFailed.CreateWallet" = "Create a New Wallet";
"Wallet.RestoreFailed.EnterWords" = "Enter 24 words";
"Wallet.Sending.Title" = "Sending Grams";
"Wallet.Sending.Text" = "Please wait a few seconds for your transaction to be processed...";
"Wallet.Sending.Title" = "Sending Grams";
"Wallet.Sent.Title" = "Done!";
"Wallet.Sent.Text" = "**%@ Grams** have been sent.";
"Wallet.Sent.ViewWallet" = "View My Wallet";
"Wallet.SecureStorageNotAvailable.Title" = "Set a Passcode";
"Wallet.SecureStorageNotAvailable.Text" = "Please set up a Passcode on your device to enable secure payments with your Gram wallet.";
"Wallet.SecureStorageReset.Title" = "Security Settings Have Changed";
"Wallet.SecureStorageReset.BiometryTouchId" = "Touch ID";
"Wallet.SecureStorageReset.BiometryFaceId" = "Face ID";
"Wallet.SecureStorageReset.BiometryText" = "Unfortunately, your wallet is no longer available because your system Passcode or %@ has been turned off. Please enable them before proceeding.";
"Wallet.SecureStorageReset.PasscodeText" = "Unfortunately, your wallet is no longer available because your system Passcode has been turned off. Please enable it before proceeding.";
"Wallet.SecureStorageChanged.BiometryText" = "Unfortunately, your wallet is no longer available due to the change in your system security settings (Passcode/%@). To restore your wallet, tap \"Import existing wallet\".";
"Wallet.SecureStorageChanged.PasscodeText" = "Unfortunately, your wallet is no longer available due to the change in your system security settings (Passcode). To restore your wallet, tap \"Import existing wallet\".";
"Wallet.SecureStorageChanged.ImportWallet" = "Import Existing Wallet";
"Wallet.SecureStorageChanged.CreateWallet" = "Create New Wallet";
"Wallet.TransactionInfo.Title" = "Transaction";
"Wallet.TransactionInfo.NoAddress" = "No Address";
"Wallet.TransactionInfo.RecipientHeader" = "RECIPIENT";
"Wallet.TransactionInfo.SenderHeader" = "SENDER";
"Wallet.TransactionInfo.CopyAddress" = "Copy Wallet Address";
"Wallet.TransactionInfo.AddressCopied" = "Address copied to clipboard.";
"Wallet.TransactionInfo.SendGrams" = "Send Grams to This Address";
"Wallet.TransactionInfo.CommentHeader" = "COMMENT";
"Wallet.TransactionInfo.StorageFeeHeader" = "STORAGE FEE";
"Wallet.TransactionInfo.OtherFeeHeader" = "TRANSACTION FEE";
"Wallet.TransactionInfo.StorageFeeInfo" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet and processing your transactions.";
"Wallet.TransactionInfo.StorageFeeInfoUrl" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet and processing your transactions. [More info]()";
"Wallet.TransactionInfo.OtherFeeInfo" = "Blockchain validators collect a tiny fee for processing your decentralized transactions.";
"Wallet.TransactionInfo.OtherFeeInfoUrl" = "Blockchain validators collect a tiny fee for processing your decentralized transactions. [More info]()";
"Wallet.WordCheck.Title" = "Test Time!";
"Wallet.WordCheck.Text" = "Lets check that you wrote them down correctly. Please enter the words\n**%1$@**, **%2$@** and **%3$@**";
"Wallet.WordCheck.Continue" = "Continue";
"Wallet.WordCheck.IncorrectHeader" = "Incorrect words!";
"Wallet.WordCheck.IncorrectText" = "The secret words you have entered do not match the ones in the list.";
"Wallet.WordCheck.TryAgain" = "Try Again";
"Wallet.WordCheck.ViewWords" = "View Words";
"Wallet.WordImport.Title" = "24 Secret Words";
"Wallet.WordImport.Text" = "Please restore access to your wallet by\nentering the 24 secret words you wrote down when creating the wallet.";
"Wallet.WordImport.Continue" = "Continue";
"Wallet.WordImport.CanNotRemember" = "I don't have them";
"Wallet.WordImport.IncorrectTitle" = "Incorrect words";
"Wallet.WordImport.IncorrectText" = "Sorry, you have entered incorrect secret words. Please double check and try again.";
"Wallet.Words.Title" = "24 Secret Words";
"Wallet.Words.Text" = "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 device.";
"Wallet.Words.Done" = "Done";
"Wallet.Words.NotDoneTitle" = "Sure Done?";
"Wallet.Words.NotDoneText" = "You didn't have enough time to write those words down.";
"Wallet.Words.NotDoneOk" = "OK, Sorry";
"Wallet.Words.NotDoneResponse" = "Apologies Accepted";
"Wallet.Send.NetworkErrorTitle" = "No network";
"Wallet.Send.NetworkErrorText" = "Couldn't send grams. Please make sure your internet connection is working and try again.";
"Wallet.Send.ErrorNotEnoughFundsTitle" = "Insufficient Grams";
"Wallet.Send.ErrorNotEnoughFundsText" = "Unfortunately, your transfer couldn't be completed. You don't have enough grams.";
"Wallet.Send.ErrorInvalidAddress" = "Invalid wallet address. Please correct and try again.";
"Wallet.Send.ErrorDecryptionFailed" = "Please make sure that your device has a passcode set in iOS Settings and try again.";
"Wallet.Send.UninitializedTitle" = "Warning";
"Wallet.Send.UninitializedText" = "This address belongs to an empty wallet. Are you sure you want to transfer grams to it?";
"Wallet.Send.SendAnyway" = "Send Anyway";
"Wallet.Receive.CreateInvoice" = "Create Invoice";
"Wallet.Receive.CreateInvoiceInfo" = "You can specify the amount and purpose of the payment to save the sender some time.";
"Wallet.Configuration.Title" = "Server Settings";
"Wallet.Configuration.Apply" = "Save";
"Wallet.Configuration.SourceHeader" = "SOURCE";
"Wallet.Configuration.SourceURL" = "URL";
"Wallet.Configuration.SourceJSON" = "JSON";
"Wallet.Configuration.SourceInfo" = "Using a different configuration allows you to change Lite Server addresses.";
"Wallet.Configuration.BlockchainIdHeader" = "BLOCKCHAIN ID";
"Wallet.Configuration.BlockchainIdPlaceholder" = "Blockchain ID";
"Wallet.Configuration.BlockchainIdInfo" = "This setting is for developers. Change it only if you are working on creating your own TON network.";
"Wallet.Configuration.ApplyErrorTitle" = "Error";
"Wallet.Configuration.ApplyErrorTextURLInvalid" = "The URL you have entered is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextURLUnreachable" = "There was an error while downloading configuration from %@\nPlease try again.";
"Wallet.Configuration.ApplyErrorTextURLInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextJSONInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.BlockchainNameChangedTitle" = "Warning";
"Wallet.Configuration.BlockchainNameChangedText" = "Are you sure you want to change the blockchain ID? You don't need this unless you're testing your own TON network.\n\nIf you proceed, you will need to reconnect your wallet using 24 secret words.";
"Wallet.Configuration.BlockchainNameChangedProceed" = "Proceed";
"Wallet.CreateInvoice.Title" = "Create Invoice";
"Wallet.Navigation.Close" = "Close";
"Wallet.Navigation.Back" = "Back";
"Wallet.Navigation.Done" = "Done";
"Wallet.Navigation.Cancel" = "Cancel";
"Wallet.Alert.OK" = "OK";
"Wallet.Alert.Cancel" = "Cancel";
"Wallet.Month.GenJanuary" = "January";
"Wallet.Month.GenFebruary" = "February";
"Wallet.Month.GenMarch" = "March";
"Wallet.Month.GenApril" = "April";
"Wallet.Month.GenMay" = "May";
"Wallet.Month.GenJune" = "June";
"Wallet.Month.GenJuly" = "July";
"Wallet.Month.GenAugust" = "August";
"Wallet.Month.GenSeptember" = "September";
"Wallet.Month.GenOctober" = "October";
"Wallet.Month.GenNovember" = "November";
"Wallet.Month.GenDecember" = "December";
"Wallet.Month.ShortJanuary" = "Jan";
"Wallet.Month.ShortFebruary" = "Feb";
"Wallet.Month.ShortMarch" = "Mar";
"Wallet.Month.ShortApril" = "Apr";
"Wallet.Month.ShortMay" = "May";
"Wallet.Month.ShortJune" = "Jun";
"Wallet.Month.ShortJuly" = "Jul";
"Wallet.Month.ShortAugust" = "Aug";
"Wallet.Month.ShortSeptember" = "Sep";
"Wallet.Month.ShortOctober" = "Oct";
"Wallet.Month.ShortNovember" = "Nov";
"Wallet.Month.ShortDecember" = "Dec";
"Wallet.Weekday.Today" = "Today";
"Wallet.Weekday.Yesterday" = "Yesterday";
"Wallet.Info.TransactionDateHeader" = "%1$@ %2$@";
"Wallet.Info.TransactionDateHeaderYear" = "%1$@ %2$@, %3$@";
"Wallet.UnknownError" = "An error occurred. Please try again later.";
"Wallet.ContextMenuCopy" = "Copy";
"Wallet.Time.PreciseDate_m1" = "Jan %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m2" = "Feb %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m3" = "Mar %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m4" = "Apr %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m5" = "May %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m6" = "Jun %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m7" = "Jul %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m8" = "Aug %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m9" = "Sep %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m10" = "Oct %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m11" = "Nov %1$@, %2$@ at %3$@";
"Wallet.Time.PreciseDate_m12" = "Dec %1$@, %2$@ at %3$@";
"Wallet.VoiceOver.Editing.ClearText" = "Clear text";
"Wallet.Receive.ShareInvoiceUrlInfo" = "Share this link with other Gram wallet owners to receive %@ Grams from them.";
"Wallet.AccessDenied.Title" = "Please Allow Access";
"Wallet.AccessDenied.Camera" = "TON Wallet needs access to your camera to take photos and videos.\n\nPlease go to Settings > Privacy > Camera and set TON Wallet to ON.";
"Wallet.AccessDenied.Settings" = "Settings";

@ -1 +1 @@
Subproject commit b8755bd2884d6bf651827c30e00bd0ea318e41a2
Subproject commit f7f2b6d7c952f3cf6bdcedce6a0a2a40a27ff596

@ -1 +1 @@
Subproject commit d6f9a87d70781e92b95b9344c7d21d921ccc3ae2
Subproject commit 21c0ca93b0cd44e7eb500a1c02729a08b496b6c2

@ -1 +1 @@
Subproject commit 44e8c29afe3baa7f5fc434f4a7e83f7ac786644e
Subproject commit ed81c15f9b577880c13b987101100cbac03f45c2

View File

@ -1 +1 @@
3.4.1
3.7.0

Some files were not shown because too many files have changed in this diff Show More