Merge commit '41bcbd14f0dd7c01d45570fd36ae0ecef1d38530' into beta
3
.bazelrc
@ -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
@ -27,6 +27,7 @@ DerivedData
|
||||
buck-out/*
|
||||
.buckd/*
|
||||
tools/buck
|
||||
tools/bazel
|
||||
AppBinary.xcworkspace/*
|
||||
Project.xcodeproj/*
|
||||
Watch/Watch.xcodeproj/*
|
||||
|
||||
@ -24,7 +24,7 @@ internal:
|
||||
name: internal
|
||||
artifacts:
|
||||
paths:
|
||||
- build/artifacts/Telegram.DSYMs.zip
|
||||
- build/artifacts
|
||||
expire_in: 1 week
|
||||
|
||||
experimental:
|
||||
|
||||
40
Makefile
@ -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
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
gCh0ST/jBZ+NM8mvcBcsd12A5FMFT4q6fETcWd5elO0=
|
||||
E65Wt9QZyVD8tvGhCJD3My6x57eDORYaiYh6HR7T3fI=
|
||||
|
||||
279
Telegram/BUILD
@ -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 = [
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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]];
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
@implementation Serialization
|
||||
|
||||
- (NSUInteger)currentLayer {
|
||||
return 120;
|
||||
return 122;
|
||||
}
|
||||
|
||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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] = []
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
16
Telegram/Telegram-iOS/AddAlternateIcons.sh
Normal 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"
|
||||
75
Telegram/Telegram-iOS/AlternateIcons-iPad.plist
Normal 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>
|
||||
69
Telegram/Telegram-iOS/AlternateIcons.plist
Normal 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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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";
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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",
|
||||
)
|
||||
|
||||
@ -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
|
||||
136
Wallet/BUCK
@ -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",
|
||||
)
|
||||
189
Wallet/BUILD
@ -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",
|
||||
],
|
||||
)
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 677 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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.";
|
||||
@ -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>
|
||||
@ -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
|
||||
```
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import UIKit
|
||||
|
||||
@objc(Application) class Application: UIApplication {
|
||||
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, @"Application", @"AppDelegate");
|
||||
}
|
||||
}
|
||||
@ -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" = "You’re 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" = "Let’s 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
|
||||
@ -1 +1 @@
|
||||
3.4.1
|
||||
3.7.0
|
||||
|
||||