Separate makefiles

This commit is contained in:
Peter 2019-10-08 19:38:14 +04:00
commit 26f8bdceb5
75 changed files with 1343 additions and 700 deletions

View File

@ -24,10 +24,11 @@ def app_binary_configs():
config = {
"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES": "YES",
"DEVELOPMENT_LANGUAGE": DEVELOPMENT_LANGUAGE,
"EXECUTABLE_NAME": "Wallet",
"PRODUCT_BUNDLE_IDENTIFIER": bundle_identifier(suffix=""),
"CODE_SIGN_ENTITLEMENTS": get_codesign_entitlements("app"),
"DEVELOPMENT_TEAM": get_development_team(),
"ASSETCATALOG_COMPILER_APPICON_NAME": "AppIconLLC",
"ASSETCATALOG_COMPILER_APPICON_NAME": "AppIconWallet",
"BUILD_NUMBER": get_build_number(),
"PRODUCT_BUNDLE_SHORT_VERSION": get_short_version(),
"APP_NAME": "TON Wallet",
@ -45,14 +46,14 @@ def app_binary_configs():
def app_info_plist_substitutions():
substitutions = {
"DEVELOPMENT_LANGUAGE": DEVELOPMENT_LANGUAGE,
"EXECUTABLE_NAME": "TON Wallet",
"EXECUTABLE_NAME": "Wallet",
"PRODUCT_BUNDLE_IDENTIFIER": bundle_identifier(suffix=""),
"PRODUCT_NAME": "TON Wallet",
"APP_NAME": "TON Wallet",
"CURRENT_PROJECT_VERSION": "1",
"BUILD_NUMBER": get_build_number(),
"PRODUCT_BUNDLE_SHORT_VERSION": get_short_version(),
"ASSETCATALOG_COMPILER_APPICON_NAME": "AppIconLLC",
"ASSETCATALOG_COMPILER_APPICON_NAME": "AppIconWallet",
"TARGETED_DEVICE_FAMILY": "1,2",
}
return substitutions

View File

@ -1,17 +1,6 @@
.PHONY : check_env build build_arm64 build_debug_arm64 package package_arm64 app app_arm64 app_debug_arm64 build_buckdebug build_verbose kill_xcode clean project project_buckdebug temp
BUCK_DEBUG_OPTIONS=\
--config custom.other_cflags="-O0 -D DEBUG" \
--config custom.other_cxxflags="-O0 -D DEBUG" \
--config custom.optimization="-Onone" \
--config custom.config_swift_compiler_flags="-DDEBUG"
BUCK_RELEASE_OPTIONS=\
--config custom.other_cflags="-Os" \
--config custom.other_cxxflags="-Os" \
--config custom.optimization="-O" \
--config custom.config_swift_compiler_flags="-whole-module-optimization"
include Utils.makefile
BUCK_OPTIONS=\
--config custom.appVersion="5.12" \
@ -50,43 +39,6 @@ BUCK_OPTIONS=\
--config custom.developmentProvisioningProfileWatchExtension="${DEVELOPMENT_PROVISIONING_PROFILE_WATCH_EXTENSION}" \
--config custom.distributionProvisioningProfileWatchExtension="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_EXTENSION}"
WALLET_BUCK_OPTIONS=\
--config custom.appVersion="1.0" \
--config custom.developmentCodeSignIdentity="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \
--config custom.distributionCodeSignIdentity="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \
--config custom.developmentTeam="${DEVELOPMENT_TEAM}" \
--config custom.baseApplicationBundleId="${WALLET_BUNDLE_ID}" \
--config custom.buildNumber="${BUILD_NUMBER}" \
--config custom.entitlementsApp="${WALLET_ENTITLEMENTS_APP}" \
--config custom.developmentProvisioningProfileApp="${WALLET_DEVELOPMENT_PROVISIONING_PROFILE_APP}" \
--config custom.distributionProvisioningProfileApp="${WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP}" \
--config custom.apiId="${API_ID}" \
--config custom.apiHash="${API_HASH}" \
--config custom.hockeyAppId="${HOCKEYAPP_ID}" \
--config custom.isInternalBuild="${IS_INTERNAL_BUILD}" \
--config custom.isAppStoreBuild="${IS_APPSTORE_BUILD}" \
--config custom.appStoreId="${APPSTORE_ID}" \
--config custom.appSpecificUrlScheme="${APP_SPECIFIC_URL_SCHEME}"
BUCK_THREADS_OPTIONS=--config build.threads=$(shell sysctl -n hw.logicalcpu)
BUCK_CACHE_OPTIONS=
ifneq ($(BUCK_HTTP_CACHE),)
ifeq ($(BUCK_CACHE_MODE),)
BUCK_CACHE_MODE=readwrite
endif
BUCK_CACHE_OPTIONS=\
--config cache.mode=http \
--config cache.http_url="$(BUCK_HTTP_CACHE)" \
--config cache.http_mode="$(BUCK_CACHE_MODE)"
endif
check_env:
ifndef BUCK
$(error BUCK is not set)
endif
sh check_env.sh
build_arm64: check_env
$(BUCK) build \
@ -148,10 +100,6 @@ build_wallet_debug_arm64: check_env
//submodules/MtProtoKit:MtProtoKit#shared,iphoneos-arm64 \
//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#dwarf-and-dsym,shared,iphoneos-arm64 \
//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared,iphoneos-arm64 \
//submodules/Postbox:Postbox#dwarf-and-dsym,shared,iphoneos-arm64 \
//submodules/Postbox:Postbox#shared,iphoneos-arm64 \
//submodules/TelegramCore:TelegramCore#dwarf-and-dsym,shared,iphoneos-arm64 \
//submodules/TelegramCore:TelegramCore#shared,iphoneos-arm64 \
//submodules/AsyncDisplayKit:AsyncDisplayKit#dwarf-and-dsym,shared,iphoneos-arm64 \
//submodules/AsyncDisplayKit:AsyncDisplayKit#shared,iphoneos-arm64 \
//submodules/Display:Display#dwarf-and-dsym,shared,iphoneos-arm64 \
@ -228,7 +176,7 @@ package_arm64:
PACKAGE_PROVISIONING_PROFILE_WATCH_APP="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_APP}" \
PACKAGE_PROVISIONING_PROFILE_WATCH_EXTENSION="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_EXTENSION}" \
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
sh package_app.sh iphoneos-arm64 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
sh package_app.sh iphoneos-arm64 $(BUCK) "telegram" $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
package_armv7:
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
@ -248,7 +196,7 @@ package_armv7:
PACKAGE_PROVISIONING_PROFILE_WATCH_APP="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_APP}" \
PACKAGE_PROVISIONING_PROFILE_WATCH_EXTENSION="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_EXTENSION}" \
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
sh package_app.sh iphoneos-armv7 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
sh package_app.sh iphoneos-armv7 $(BUCK) "telegram" $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
package_debug_arm64:
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
@ -270,7 +218,7 @@ package_debug_arm64:
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
ENABLE_GET_TASK_ALLOW=0 \
CODESIGNING_PROFILES_VARIANT="development" \
sh package_app.sh iphoneos-arm64 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
sh package_app.sh iphoneos-arm64 $(BUCK) "telegram" $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
package_debug_armv7:
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
@ -292,7 +240,7 @@ package_debug_armv7:
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
ENABLE_GET_TASK_ALLOW=0 \
CODESIGNING_PROFILES_VARIANT="development" \
sh package_app.sh iphoneos-armv7 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
sh package_app.sh iphoneos-armv7 $(BUCK) "telegram" $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
package:
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
@ -312,7 +260,7 @@ package:
PACKAGE_PROVISIONING_PROFILE_WATCH_APP="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_APP}" \
PACKAGE_PROVISIONING_PROFILE_WATCH_EXTENSION="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_EXTENSION}" \
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
sh package_app.sh iphoneos-arm64,iphoneos-armv7 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
sh package_app.sh iphoneos-arm64,iphoneos-armv7 $(BUCK) "telegram" $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
app: build package
@ -400,9 +348,6 @@ build_ton: check_env
//submodules/ton:ton#iphoneos-arm64 \
--verbose 7 ${BUCK_OPTIONS} ${BUCK_THREADS_OPTIONS} ${BUCK_DEBUG_OPTIONS}
kill_xcode:
killall Xcode || true
clean: kill_xcode
sh clean.sh
@ -410,14 +355,6 @@ project: check_env kill_xcode
$(BUCK) project //:workspace --config custom.mode=project ${BUCK_OPTIONS} ${BUCK_DEBUG_OPTIONS}
open Telegram_Buck.xcworkspace
wallet_deps: check_env
$(BUCK) query "deps(//Wallet:AppPackage)" \
${WALLET_BUCK_OPTIONS} ${BUCK_DEBUG_OPTIONS}
wallet_project: check_env kill_xcode
$(BUCK) project //Wallet:workspace --config custom.mode=project ${WALLET_BUCK_OPTIONS} ${BUCK_DEBUG_OPTIONS}
open Wallet/WalletWorkspace.xcworkspace
project_opt: check_env kill_xcode
$(BUCK) project //:workspace --config custom.mode=project ${BUCK_OPTIONS} ${BUCK_RELEASE_OPTIONS}
open Telegram_Buck.xcworkspace

View File

@ -4756,7 +4756,7 @@ Any member of this group will be able to see messages in the channel.";
"ChatSearch.ResultsTooltip" = "Tap to view as a list.";
"Wallet.Updated.JustNow" = "just now";
"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
@ -4778,6 +4778,7 @@ Any member of this group will be able to see messages in the channel.";
"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.";

40
Utils.makefile Normal file
View File

@ -0,0 +1,40 @@
export BUCK_DEBUG_OPTIONS=\
--config custom.other_cflags="-O0 -D DEBUG" \
--config custom.other_cxxflags="-O0 -D DEBUG" \
--config custom.optimization="-Onone" \
--config custom.config_swift_compiler_flags="-DDEBUG"
export BUCK_RELEASE_OPTIONS=\
--config custom.other_cflags="-Os" \
--config custom.other_cxxflags="-Os" \
--config custom.optimization="-O" \
--config custom.config_swift_compiler_flags="-whole-module-optimization"
export BUCK_THREADS_OPTIONS=--config build.threads=$(shell sysctl -n hw.logicalcpu)
ifneq ($(BUCK_HTTP_CACHE),)
ifeq ($(BUCK_CACHE_MODE),)
BUCK_CACHE_MODE=readwrite
endif
export BUCK_CACHE_OPTIONS=\
--config cache.mode=http \
--config cache.http_url="$(BUCK_HTTP_CACHE)" \
--config cache.http_mode="$(BUCK_CACHE_MODE)"
endif
ifneq ($(BUCK_DIR_CACHE),)
export BUCK_CACHE_OPTIONS=\
--config cache.mode=dir \
--config cache.dir="$(BUCK_DIR_CACHE)" \
--config cache.dir_mode="readwrite"
endif
check_env:
ifndef BUCK
$(error BUCK is not set)
endif
sh check_env.sh
kill_xcode:
killall Xcode || true

52
Wallet.makefile Normal file
View File

@ -0,0 +1,52 @@
include Utils.makefile
WALLET_BUCK_OPTIONS=\
--config custom.appVersion="1.0" \
--config custom.developmentCodeSignIdentity="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \
--config custom.distributionCodeSignIdentity="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \
--config custom.developmentTeam="${DEVELOPMENT_TEAM}" \
--config custom.baseApplicationBundleId="${WALLET_BUNDLE_ID}" \
--config custom.buildNumber="${BUILD_NUMBER}" \
--config custom.entitlementsApp="${WALLET_ENTITLEMENTS_APP}" \
--config custom.developmentProvisioningProfileApp="${WALLET_DEVELOPMENT_PROVISIONING_PROFILE_APP}" \
--config custom.distributionProvisioningProfileApp="${WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP}" \
--config custom.apiId="${API_ID}" \
--config custom.apiHash="${API_HASH}" \
--config custom.hockeyAppId="${HOCKEYAPP_ID}" \
--config custom.isInternalBuild="${IS_INTERNAL_BUILD}" \
--config custom.isAppStoreBuild="${IS_APPSTORE_BUILD}" \
--config custom.appStoreId="${APPSTORE_ID}" \
--config custom.appSpecificUrlScheme="${APP_SPECIFIC_URL_SCHEME}"
wallet_deps: check_env
$(BUCK) query "deps(//Wallet:AppPackage)" --output-attribute buck.type \
${WALLET_BUCK_OPTIONS} ${BUCK_RELEASE_OPTIONS}
wallet_project: check_env kill_xcode
$(BUCK) project //Wallet:workspace --config custom.mode=project ${WALLET_BUCK_OPTIONS} ${BUCK_DEBUG_OPTIONS}
open Wallet/WalletWorkspace.xcworkspace
build_wallet: check_env
$(BUCK) build \
//Wallet:AppPackage#iphoneos-arm64,iphoneos-armv7 \
//Wallet:Wallet#dwarf-and-dsym,iphoneos-arm64,iphoneos-armv7 \
//submodules/MtProtoKit:MtProtoKit#dwarf-and-dsym,shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/MtProtoKit:MtProtoKit#shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#dwarf-and-dsym,shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/AsyncDisplayKit:AsyncDisplayKit#dwarf-and-dsym,shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/AsyncDisplayKit:AsyncDisplayKit#shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/Display:Display#dwarf-and-dsym,shared,iphoneos-arm64,iphoneos-armv7 \
//submodules/Display:Display#shared,iphoneos-arm64,iphoneos-armv7 \
${WALLET_BUCK_OPTIONS} ${BUCK_RELEASE_OPTIONS} ${BUCK_THREADS_OPTIONS} ${BUCK_CACHE_OPTIONS}
wallet_package:
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
PACKAGE_CODE_SIGN_IDENTITY="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \
PACKAGE_PROVISIONING_PROFILE_APP="${WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP}" \
PACKAGE_ENTITLEMENTS_APP="Wallet/${WALLET_ENTITLEMENTS_APP}" \
PACKAGE_BUNDLE_ID="${WALLET_BUNDLE_ID}" \
sh package_app.sh iphoneos-arm64,iphoneos-armv7 $(BUCK) "wallet" $(WALLET_BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
wallet_app: build_wallet wallet_package

View File

@ -52,7 +52,7 @@ apple_asset_catalog(
dirs = [
"Icons.xcassets",
],
app_icon = "AppIconLLC",
app_icon = "AppIconWallet",
visibility = ["PUBLIC"],
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 159 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -68,6 +68,10 @@
</dict>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSCameraUsageDescription</key>
<string>Please allow TON Wallet access to your camera for scanning QR codes.</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>

View File

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

View File

@ -4,6 +4,8 @@ import SwiftSignalKit
import BuildConfig
import WalletUI
import WalletCore
import AVFoundation
import MtProtoKit
private func encodeText(_ string: String, _ key: Int) -> String {
var result = ""
@ -120,27 +122,173 @@ private class ApplicationStatusBarHost: StatusBarHost {
}
}
private let records = Atomic<[WalletStateRecord]>(value: [])
private final class WalletStorageInterfaceImpl: WalletStorageInterface {
func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> {
return .single(records.with { $0 })
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 getWalletRecords() -> Signal<[WalletStateRecord], NoError> {
return .single(records.with { $0 })
func get() -> Data? {
if let data = self.data {
return data
} else {
self.data = try? Data(contentsOf: URL(fileURLWithPath: self.path))
return self.data
}
}
func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> {
return .single(records.modify(f))
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 WalletContextImpl: WalletContext {
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
init(path: String) {
self.storage = FileBackedStorage(path: path)
}
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)
}
}
}
}
private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let storage: WalletStorageInterface
let tonInstance: TonInstance
let keychain: TonKeychain
let presentationData: WalletPresentationData
let window: Window1
private var currentImagePickerCompletion: ((UIImage) -> Void)?
var inForeground: Signal<Bool, NoError> {
return .single(true)
@ -151,7 +299,7 @@ private final class WalletContextImpl: WalletContext {
}
func presentNativeController(_ controller: UIViewController) {
self.window.presentNative(controller)
}
func idleTimerExtension() -> Disposable {
@ -159,32 +307,75 @@ private final class WalletContextImpl: WalletContext {
}
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) {
completion()
AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
Queue.mainQueue().async {
if response {
completion()
}
}
}
}
func pickImage(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)
}
init(basePath: String, config: String, blockchainName: String, navigationBarTheme: NavigationBarTheme) {
self.storage = WalletStorageInterfaceImpl()
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, config: String, blockchainName: String, navigationBarTheme: NavigationBarTheme, window: Window1) {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: basePath + "/keys"), withIntermediateDirectories: true, attributes: nil)
self.storage = WalletStorageInterfaceImpl(path: basePath + "/data")
self.window = window
self.tonInstance = TonInstance(
basePath: basePath,
basePath: basePath + "/keys",
config: config,
blockchainName: blockchainName,
proxy: nil
proxy: nil /*TonProxyImpl()*/
)
let baseAppBundleId = Bundle.main.bundleIdentifier!
#if targetEnvironment(simulator)
self.keychain = TonKeychain(encryptionPublicKey: {
return .single(Data())
}, encrypt: { data in
@ -192,6 +383,47 @@ private final class WalletContextImpl: WalletContext {
}, 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
let accentColor = UIColor(rgb: 0x007ee5)
self.presentationData = WalletPresentationData(
theme: WalletTheme(
@ -271,6 +503,8 @@ private final class WalletContextImpl: WalletContext {
groupingSeparator: " "
)
)
super.init()
}
}
@ -284,18 +518,20 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let statusBarHost = ApplicationStatusBarHost()
let (window, hostView) = nativeWindowHostView()
self.mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
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: .blue,
disabledButtonColor: .gray,
buttonColor: accentColor,
disabledButtonColor: UIColor(rgb: 0xd0d0d0),
primaryTextColor: .black,
backgroundColor: .lightGray,
separatorColor: .black,
badgeBackgroundColor: .red,
badgeStrokeColor: .red,
backgroundColor: UIColor(rgb: 0xf7f7f7),
separatorColor: UIColor(rgb: 0xb1b1b1),
badgeBackgroundColor: UIColor(rgb: 0xff3b30),
badgeStrokeColor: UIColor(rgb: 0xff3b30),
badgeTextColor: .white
)
@ -309,6 +545,7 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
)
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
print("Starting with \(documentsPath)")
let config =
"""
@ -336,16 +573,230 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
}
"""
let walletContext = WalletContextImpl(basePath: documentsPath, config: config, blockchainName: "testnet", navigationBarTheme: navigationBarTheme)
let walletContext = WalletContextImpl(basePath: documentsPath, config: config, blockchainName: "testnet", navigationBarTheme: navigationBarTheme, window: mainWindow)
self.walletContext = walletContext
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
self.mainWindow?.viewController = navigationController
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 {
print("publicKey = \(publicKey.base64EncodedString())")
if record.info.encryptedSecret.publicKey == publicKey {
if record.exportCompleted {
let _ = (walletAddress(publicKey: record.info.publicKey, tonInstance: walletContext.tonInstance)
|> deliverOnMainQueue).start(next: { address in
let infoScreen = WalletInfoScreen(context: walletContext, walletInfo: record.info, address: address, enableDebugActions: false)
navigationController.setViewControllers([infoScreen], animated: false)
})
} else {
let createdScreen = WalletSplashScreen(context: walletContext, mode: .created(record.info, nil), walletCreatedPreloadState: nil)
navigationController.setViewControllers([createdScreen], animated: false)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageReset(.changed), walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: WalletSplashMode.secureStorageReset(.notAvailable), walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
}
} else {
if publicKey != nil {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
}
}
})
mainWindow.viewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
}
private final class Serialization: NSObject, MTSerialization {
func currentLayer() -> UInt {
return 106
}
func parseMessage(_ data: Data!) -> Any! {
return nil
}
func exportAuthorization(_ datacenterId: Int32, data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTExportAuthorizationResponseParser! {
return nil
}
func importAuthorization(_ authId: Int32, bytes: Data!) -> Data! {
return Data()
}
func requestDatacenterAddress(with data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTRequestDatacenterAddressListParser! {
return { _ in
return nil
}
}
func requestNoop(_ data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTRequestNoopParser! {
return { _ in
return nil
}
}
}
private final class Keychain: NSObject, MTKeychain {
let get: (String) -> Data?
let set: (String, Data) -> Void
let remove: (String) -> Void
init(get: @escaping (String) -> Data?, set: @escaping (String, Data) -> Void, remove: @escaping (String) -> Void) {
self.get = get
self.set = set
self.remove = remove
}
func setObject(_ object: Any!, forKey aKey: String!, group: String!) {
if let object = object {
let data = NSKeyedArchiver.archivedData(withRootObject: object)
self.set(group + ":" + aKey, data)
} else {
self.remove(group + ":" + aKey)
}
}
func object(forKey aKey: String!, group: String!) -> Any! {
if let data = self.get(group + ":" + aKey) {
return NSKeyedUnarchiver.unarchiveObject(with: data as Data)
}
return nil
}
func removeObject(forKey aKey: String!, group: String!) {
self.remove(group + ":" + aKey)
}
func dropGroup(_ group: String!) {
}
}
private final class TonProxyImpl: TonNetworkProxy {
private let context: MTContext
private let mtProto: MTProto
private let requestService: MTRequestMessageService
init() {
let serialization = Serialization()
var apiEnvironment = MTApiEnvironment()
apiEnvironment.apiId = 8
apiEnvironment.langPack = "ios"
apiEnvironment.layer = serialization.currentLayer() as NSNumber
apiEnvironment.disableUpdates = true
apiEnvironment = apiEnvironment.withUpdatedLangPackCode("en")
self.context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment, isTestingEnvironment: false, useTempAuthKeys: false)
let seedAddressList: [Int: [String]]
seedAddressList = [
1: ["149.154.175.50", "2001:b28:f23d:f001::a"],
2: ["149.154.167.50", "2001:67c:4e8:f002::a"],
3: ["149.154.175.100", "2001:b28:f23d:f003::a"],
4: ["149.154.167.91", "2001:67c:4e8:f004::a"],
5: ["149.154.171.5", "2001:b28:f23f:f005::a"]
]
for (id, ips) in seedAddressList {
self.context.setSeedAddressSetForDatacenterWithId(id, seedAddressSet: MTDatacenterAddressSet(addressList: ips.map { MTDatacenterAddress(ip: $0, port: 443, preferForMedia: false, restrictToTcp: false, cdn: false, preferForProxy: false, secret: nil)! }))
}
let keychainDict = Atomic<[String: Data]>(value: [:])
self.context.keychain = Keychain(get: { key in
return keychainDict.with { dict -> Data? in
return dict[key]
}
}, set: { key, value in
let _ = keychainDict.modify { dict in
var dict = dict
dict[key] = value
return dict
}
}, remove: { key in
let _ = keychainDict.modify { dict in
var dict = dict
dict.removeValue(forKey: key)
return dict
}
})
let mtProto = MTProto(context: self.context, datacenterId: 2, usageCalculationInfo: nil)!
mtProto.useTempAuthKeys = self.context.useTempAuthKeys
mtProto.checkForProxyConnectionIssues = false
self.mtProto = mtProto
self.requestService = MTRequestMessageService(context: context)!
mtProto.add(self.requestService)
self.mtProto.resume()
}
func request(data: Data, timeout: Double, completion: @escaping (TonNetworkProxyResult) -> Void) -> Disposable {
let request = MTRequest()
let outputStream = MTOutputStream()
//wallet.sendLiteRequest#e2c9d33e body:bytes = wallet.LiteResponse;
outputStream.write(Int32(bitPattern: 0xe2c9d33e as UInt32))
outputStream.writeBytes(data)
request.setPayload(outputStream.currentBytes(), metadata: "wallet.sendLiteRequest", shortMetadata: "wallet.sendLiteRequest", responseParser: { response in
guard let response = response else {
return nil
}
let inputStream = MTInputStream(data: response)!
//wallet.liteResponse#764386d7 response:bytes = wallet.LiteResponse;
let signature = inputStream.readInt32()
if (signature != 0x764386d7 as Int32) {
return nil
}
return inputStream.readBytes()
})
request.dependsOnPasswordEntry = false
request.shouldContinueExecutionWithErrorContext = { _ in
return true
};
request.completed = { response, _, error in
if let response = response as? Data {
completion(.reponse(response))
} else {
completion(.error(error?.errorDescription ?? "UNKNOWN ERROR"))
}
}
let requestId = request.internalId
self.requestService.add(request)
return ActionDisposable { [weak self] in
self?.requestService.removeRequest(byInternalId: requestId)
}
}
}

View File

@ -1,4 +1,4 @@
"Wallet.Updated.JustNow" = "just now";
"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
@ -19,6 +19,7 @@
"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.";

66
extract_wallet_source.py Normal file
View File

@ -0,0 +1,66 @@
import sys
import os
import json
import re
import shutil
def get_file_list(dir):
result_files = []
result_dirs = []
for root, dirs, files in os.walk(dir, topdown=False):
for name in files:
result_files.append(os.path.relpath(os.path.join(root, name), dir))
for name in dirs:
result_dirs.append(os.path.relpath(os.path.join(root, name), dir))
return set(result_dirs), set(result_files)
def clean_files(base_dir, dirs, files):
for file in files:
if file == '.DS_Store':
os.remove(base_dir + '/' + file)
for dir in dirs:
if re.match('.*\\.xcodeproj', dir) or re.match('.*\\.xcworkspace', dir):
shutil.rmtree(base_dir + '/' + dir, ignore_errors=True)
if len(sys.argv) != 2:
print('Usage: extract_wallet_source.py destination')
sys.exit(1)
destination = sys.argv[1]
deps_data = os.popen('make -f Wallet.makefile --silent wallet_deps').read()
deps = json.loads(deps_data)
paths = []
for dep in deps:
dep_type = deps[dep]['buck.type']
if dep_type == 'genrule':
continue
match = re.search('//(.+?):', dep)
if match:
dep_path = match.group(1)
if dep_path not in paths:
paths.append(dep_path)
for dep_path in paths:
shutil.copytree(dep_path, destination + '/' + dep_path)
result_dirs, result_files = get_file_list(destination)
clean_files(destination, result_dirs, result_files)
with open(destination + '/BUCK', 'w+b') as file:
pass
shutil.copytree('Config', destination + '/' + 'Config')
copy_files = [
'.buckconfig',
'Utils.makefile',
'Wallet.makefile',
'check_env.sh',
'package_app.sh',
]
for file in copy_files:
shutil.copy(file, destination + '/' + file)

View File

@ -3,13 +3,24 @@
#set -x
set -e
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
echo "Usage: sh package_app.sh path/to/buck platform-flavors type"
exit 1
fi
PLATFORM_FLAVORS="$1"
BUCK="$2"
APP_TYPE="$3"
shift
shift
shift
BUILD_PATH="build"
APP_NAME="Telegram"
if [ "$APP_TYPE" == "wallet" ]; then
APP_NAME="TONWallet"
else
APP_NAME="Telegram"
fi
IPA_PATH="$BUILD_PATH/$APP_NAME.ipa"
DSYMS_FOLDER_NAME="DSYMs"
@ -41,7 +52,11 @@ rm -rf "$TEMP_PATH"
mkdir -p "$TEMP_PATH"
mkdir -p "$TEMP_ENTITLEMENTS_PATH"
cp "buck-out/gen/AppPackage#$PLATFORM_FLAVORS.ipa" "$IPA_PATH.original"
if [ "$APP_TYPE" == "wallet" ]; then
cp "buck-out/gen/Wallet/AppPackage#$PLATFORM_FLAVORS.ipa" "$IPA_PATH.original"
else
cp "buck-out/gen/AppPackage#$PLATFORM_FLAVORS.ipa" "$IPA_PATH.original"
fi
rm -rf "$IPA_PATH.original.unpacked"
rm -f "$BUILD_PATH/${APP_NAME}_signed.ipa"
mkdir -p "$IPA_PATH.original.unpacked"
@ -51,18 +66,18 @@ unzip "$IPA_PATH.original" -d "$IPA_PATH.original.unpacked/" 1>/dev/null
rm "$IPA_PATH.original"
UNPACKED_PATH="$IPA_PATH.original.unpacked"
APP_PATH="$UNPACKED_PATH/Payload/Telegram.app"
if [ "$APP_TYPE" == "wallet" ]; then
APP_PATH="$UNPACKED_PATH/Payload/Wallet.app"
else
APP_PATH="$UNPACKED_PATH/Payload/Telegram.app"
fi
FRAMEWORKS_DIR="$APP_PATH/Frameworks"
rm -rf "$IPA_PATH.original.unpacked/SwiftSupport/iphoneos/"*
rm -rf "$IPA_PATH.original.unpacked/Symbols/"*
rm -rf "$FRAMEWORKS_DIR/"*
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: sh package_app.sh path/to/buck platform-flavors"
exit 1
fi
if [ -z "$PACKAGE_METHOD" ]; then
echo "PACKAGE_METHOD is not set"
exit 1
@ -111,14 +126,15 @@ if [ ! -d "$PROFILES_PATH" ]; then
exit 1
fi
#security delete-keychain "$KEYCHAIN_PATH" || true
rm -f "$KEYCHAIN_PATH"
#security create-keychain -p "password" "$KEYCHAIN_PATH"
#security unlock-keychain -p "password" "$KEYCHAIN_PATH"
#KEYCHAIN_FLAG="--keychain '$KEYCHAIN_PATH'"
APP_ITEMS_WITH_PROVISIONING_PROFILE="APP EXTENSION_Share EXTENSION_Widget EXTENSION_NotificationService EXTENSION_NotificationContent EXTENSION_Intents WATCH_APP WATCH_EXTENSION"
APP_ITEMS_WITH_ENTITLEMENTS="APP EXTENSION_Share EXTENSION_Widget EXTENSION_NotificationService EXTENSION_NotificationContent EXTENSION_Intents"
if [ "$APP_TYPE" == "wallet" ]; then
APP_ITEMS_WITH_PROVISIONING_PROFILE="APP"
APP_ITEMS_WITH_ENTITLEMENTS="APP"
else
APP_ITEMS_WITH_PROVISIONING_PROFILE="APP EXTENSION_Share EXTENSION_Widget EXTENSION_NotificationService EXTENSION_NotificationContent EXTENSION_Intents WATCH_APP WATCH_EXTENSION"
APP_ITEMS_WITH_ENTITLEMENTS="APP EXTENSION_Share EXTENSION_Widget EXTENSION_NotificationService EXTENSION_NotificationContent EXTENSION_Intents"
fi
COMMON_IDENTITY_HASH=""
@ -255,8 +271,14 @@ COPY_PLIST_KEYS=(\
)
APP_PLIST="$APP_PATH/Info.plist"
if [ "$APP_TYPE" == "wallet" ]; then
APP_BINARY_TARGET="//Wallet:Wallet"
else
APP_BINARY_TARGET="//:Telegram"
fi
echo "Repacking frameworks..."
for DEPENDENCY in $(${BUCK} query "kind('apple_library', deps('//:Telegram#$PLATFORM_FLAVORS', 1))" "$@"); do
for DEPENDENCY in $(${BUCK} query "kind('apple_library', deps('${APP_BINARY_TARGET}#$PLATFORM_FLAVORS', 1))" "$@"); do
DEPENDENCY_PATH=$(echo "$DEPENDENCY" | sed -e "s#^//##" | sed -e "s#:#/#")
DEPENDENCY_NAME=$(echo "$DEPENDENCY" | sed -e "s/#.*//" | sed -e "s/^.*\://")
DYLIB_PATH="buck-out/gen/$DEPENDENCY_PATH/lib$DEPENDENCY_NAME.dylib"
@ -283,23 +305,40 @@ for DEPENDENCY in $(${BUCK} query "kind('apple_library', deps('//:Telegram#$PLAT
cp -r "$DSYM_PATH" "$DSYMS_DIR/"
done
APP_BINARY_DSYM_PATH="buck-out/gen/Telegram#dwarf-and-dsym,$PLATFORM_FLAVORS,no-include-frameworks/Telegram.app.dSYM"
if [ "$APP_TYPE" == "wallet" ]; then
APP_BINARY_DSYM_PATH="buck-out/gen/Wallet/Wallet#dwarf-and-dsym,$PLATFORM_FLAVORS,no-include-frameworks/Wallet.app.dSYM"
else
APP_BINARY_DSYM_PATH="buck-out/gen/Telegram#dwarf-and-dsym,$PLATFORM_FLAVORS,no-include-frameworks/Telegram.app.dSYM"
fi
cp -r "$APP_BINARY_DSYM_PATH" "$DSYMS_DIR/"
EXTENSIONS="Share Widget Intents NotificationContent NotificationService"
if [ "$APP_TYPE" == "wallet" ]; then
EXTENSIONS=""
else
EXTENSIONS="Share Widget Intents NotificationContent NotificationService"
fi
for EXTENSION in $EXTENSIONS; do
EXTENSION_DSYM_PATH="buck-out/gen/${EXTENSION}Extension#dwarf-and-dsym,$PLATFORM_FLAVORS,no-include-frameworks/${EXTENSION}Extension.appex.dSYM"
cp -r "$EXTENSION_DSYM_PATH" "$DSYMS_DIR/"
done
WATCH_EXTENSION_DSYM_PATH="buck-out/gen/WatchAppExtension#dwarf-and-dsym,no-include-frameworks,watchos-arm64_32,watchos-armv7k/WatchAppExtension.appex.dSYM"
cp -r "$WATCH_EXTENSION_DSYM_PATH" "$DSYMS_DIR/"
if [ "$APP_TYPE" != "wallet" ]; then
WATCH_EXTENSION_DSYM_PATH="buck-out/gen/WatchAppExtension#dwarf-and-dsym,no-include-frameworks,watchos-arm64_32,watchos-armv7k/WatchAppExtension.appex.dSYM"
cp -r "$WATCH_EXTENSION_DSYM_PATH" "$DSYMS_DIR/"
fi
TEMP_DYLIB_DIR="$TEMP_PATH/SwiftSupport"
rm -rf "$TEMP_DYLIB_DIR"
mkdir -p "$TEMP_DYLIB_DIR"
mkdir -p "$TEMP_DYLIB_DIR/out"
if [ "$APP_TYPE" == "wallet" ]; then
EXECUTABLE_NAME="Wallet"
else
EXECUTABLE_NAME="Telegram"
fi
echo "Copying swift support files..."
xcrun swift-stdlib-tool \
--copy \
@ -307,7 +346,7 @@ xcrun swift-stdlib-tool \
--platform iphoneos \
--toolchain "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain" \
--source-libraries "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos" \
--scan-executable "$APP_PATH/Telegram" \
--scan-executable "$APP_PATH/$EXECUTABLE_NAME" \
--scan-folder "$APP_PATH/Frameworks" \
--scan-folder "$APP_PATH/PlugIns" \
--destination "$TEMP_DYLIB_DIR"
@ -348,7 +387,12 @@ done
echo "Signing..."
PLUGINS="Share Widget Intents NotificationService NotificationContent"
if [ "$APP_TYPE" == "wallet" ]; then
PLUGINS=""
else
PLUGINS="Share Widget Intents NotificationService NotificationContent"
fi
for PLUGIN in $PLUGINS; do
PLUGIN_PATH="$APP_PATH/PlugIns/${PLUGIN}Extension.appex"
if [ ! -d "$PLUGIN_PATH" ]; then
@ -377,52 +421,54 @@ for PLUGIN in $PLUGINS; do
/usr/bin/codesign ${VERBOSE} -f -s "$COMMON_IDENTITY_HASH" --entitlements "${!ENTITLEMENTS_PATH_VAR}" "$PLUGIN_PATH"
done
WATCH_APP_PATH="$APP_PATH/Watch/WatchApp.app"
WATCH_EXTENSION_PATH="$WATCH_APP_PATH/PlugIns/WatchAppExtension.appex"
if [ "$APP_TYPE" != "wallet" ]; then
WATCH_APP_PATH="$APP_PATH/Watch/WatchApp.app"
WATCH_EXTENSION_PATH="$WATCH_APP_PATH/PlugIns/WatchAppExtension.appex"
WATCH_EXTENSION_PROFILE_PATH_VAR="PROFILE_PATH_WATCH_EXTENSION"
if [ -z "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" ]; then
echo "$WATCH_EXTENSION_PROFILE_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" ]; then
echo "${!WATCH_EXTENSION_PROFILE_PATH_VAR} does not exist"
exit 1
fi
WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR="ENTITLEMENTS_PATH_WATCH_EXTENSION"
if [ -z "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" ]; then
echo "$WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" ]; then
echo "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR} does not exist"
exit 1
fi
WATCH_EXTENSION_PROFILE_PATH_VAR="PROFILE_PATH_WATCH_EXTENSION"
if [ -z "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" ]; then
echo "$WATCH_EXTENSION_PROFILE_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" ]; then
echo "${!WATCH_EXTENSION_PROFILE_PATH_VAR} does not exist"
exit 1
fi
WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR="ENTITLEMENTS_PATH_WATCH_EXTENSION"
if [ -z "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" ]; then
echo "$WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" ]; then
echo "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR} does not exist"
exit 1
fi
cp "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" "$WATCH_EXTENSION_PATH/embedded.mobileprovision"
/usr/bin/codesign ${VERBOSE} -f -s "$COMMON_IDENTITY_HASH" --entitlements "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" "$WATCH_EXTENSION_PATH" 2>/dev/null
cp "${!WATCH_EXTENSION_PROFILE_PATH_VAR}" "$WATCH_EXTENSION_PATH/embedded.mobileprovision"
/usr/bin/codesign ${VERBOSE} -f -s "$COMMON_IDENTITY_HASH" --entitlements "${!WATCH_EXTENSION_ENTITLEMENTS_PATH_VAR}" "$WATCH_EXTENSION_PATH" 2>/dev/null
WATCH_APP_PROFILE_PATH_VAR="PROFILE_PATH_WATCH_APP"
if [ -z "${!WATCH_APP_PROFILE_PATH_VAR}" ]; then
echo "$WATCH_APP_PROFILE_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_APP_PROFILE_PATH_VAR}" ]; then
echo "${!WATCH_APP_PROFILE_PATH_VAR} does not exist"
exit 1
fi
WATCH_APP_ENTITLEMENTS_PATH_VAR="ENTITLEMENTS_PATH_WATCH_APP"
if [ -z "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" ]; then
echo "$WATCH_APP_ENTITLEMENTS_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" ]; then
echo "${!WATCH_APP_ENTITLEMENTS_PATH_VAR} does not exist"
exit 1
fi
WATCH_APP_PROFILE_PATH_VAR="PROFILE_PATH_WATCH_APP"
if [ -z "${!WATCH_APP_PROFILE_PATH_VAR}" ]; then
echo "$WATCH_APP_PROFILE_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_APP_PROFILE_PATH_VAR}" ]; then
echo "${!WATCH_APP_PROFILE_PATH_VAR} does not exist"
exit 1
fi
WATCH_APP_ENTITLEMENTS_PATH_VAR="ENTITLEMENTS_PATH_WATCH_APP"
if [ -z "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" ]; then
echo "$WATCH_APP_ENTITLEMENTS_PATH_VAR is not defined"
exit 1
fi
if [ ! -f "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" ]; then
echo "${!WATCH_APP_ENTITLEMENTS_PATH_VAR} does not exist"
exit 1
fi
cp "${!WATCH_APP_PROFILE_PATH_VAR}" "$WATCH_APP_PATH/embedded.mobileprovision"
/usr/bin/codesign ${VERBOSE} -f -s "$COMMON_IDENTITY_HASH" --entitlements "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" "$WATCH_APP_PATH" 2>/dev/null
cp "${!WATCH_APP_PROFILE_PATH_VAR}" "$WATCH_APP_PATH/embedded.mobileprovision"
/usr/bin/codesign ${VERBOSE} -f -s "$COMMON_IDENTITY_HASH" --entitlements "${!WATCH_APP_ENTITLEMENTS_PATH_VAR}" "$WATCH_APP_PATH" 2>/dev/null
fi
APP_PROFILE_PATH_VAR="PROFILE_PATH_APP"
if [ -z "${!APP_PROFILE_PATH_VAR}" ]; then

View File

@ -389,6 +389,10 @@ public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView) {
hostView?.presentNative?(controller)
}
hostView.nativeController = { [weak rootViewController] in
return rootViewController
}
window.hitTestImpl = { [weak hostView] point, event in
return hostView?.hitTest?(point, event)
}

View File

@ -211,6 +211,7 @@ public final class WindowHostView {
var present: ((ContainableController, PresentationSurfaceLevel, Bool, @escaping () -> Void) -> Void)?
var presentInGlobalOverlay: ((_ controller: ContainableController) -> Void)?
var presentNative: ((UIViewController) -> Void)?
var nativeController: (() -> UIViewController?)?
var updateSize: ((CGSize, Double) -> Void)?
var layoutSubviews: (() -> Void)?
var updateToInterfaceOrientation: ((UIInterfaceOrientation) -> Void)?
@ -1109,7 +1110,9 @@ public class Window1 {
}
public func presentNative(_ controller: UIViewController) {
if let nativeController = self.hostView.nativeController?() {
nativeController.present(controller, animated: true, completion: nil)
}
}
private func panGestureBegan(location: CGPoint) {

View File

@ -477,7 +477,7 @@ public struct CombinedWalletState: Codable, Equatable {
public var pendingTransactions: [PendingWalletTransaction]
}
public struct WalletStateRecord: Equatable {
public struct WalletStateRecord: Codable, Equatable {
public let info: WalletInfo
public var exportCompleted: Bool
public var state: CombinedWalletState?

View File

@ -11,7 +11,7 @@ apple_resource(
apple_asset_catalog(
name = 'WalletUIAssets',
dirs = [
"Images.xcassets",
"WalletImages.xcassets",
],
visibility = ["PUBLIC"],
)

View File

@ -201,6 +201,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
private let refreshNode: WalletRefreshNode
private let balanceSubtitleNode: ImmediateTextNode
private let receiveButtonNode: SolidRoundedButtonNode
private let receiveGramsButtonNode: SolidRoundedButtonNode
private let sendButtonNode: SolidRoundedButtonNode
private let headerBackgroundNode: ASDisplayNode
private let headerCornerNode: ASImageNode
@ -229,6 +230,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
})?.stretchableImage(withLeftCapWidth: 10, topCapHeight: 1)
self.receiveButtonNode = SolidRoundedButtonNode(title: presentationData.strings.Wallet_Info_Receive, icon: UIImage(bundleImageName: "Wallet/ReceiveButtonIcon"), theme: SolidRoundedButtonTheme(backgroundColor: .white, foregroundColor: .black), height: 50.0, cornerRadius: 10.0, gloss: false)
self.receiveGramsButtonNode = SolidRoundedButtonNode(title: presentationData.strings.Wallet_Info_ReceiveGrams, icon: UIImage(bundleImageName: "Wallet/ReceiveButtonIcon"), theme: SolidRoundedButtonTheme(backgroundColor: .white, foregroundColor: .black), height: 50.0, cornerRadius: 10.0, gloss: false)
self.sendButtonNode = SolidRoundedButtonNode(title: presentationData.strings.Wallet_Info_Send, icon: UIImage(bundleImageName: "Wallet/SendButtonIcon"), theme: SolidRoundedButtonTheme(backgroundColor: .white, foregroundColor: .black), height: 50.0, cornerRadius: 10.0, gloss: false)
self.refreshNode = WalletRefreshNode(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
@ -239,6 +241,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
self.addSubnode(self.headerCornerNode)
if hasActions {
self.addSubnode(self.receiveButtonNode)
self.addSubnode(self.receiveGramsButtonNode)
self.addSubnode(self.sendButtonNode)
}
self.addSubnode(self.balanceNode)
@ -248,6 +251,9 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
self.receiveButtonNode.pressed = {
receiveAction()
}
self.receiveGramsButtonNode.pressed = {
receiveAction()
}
self.sendButtonNode.pressed = {
sendAction()
}
@ -332,18 +338,18 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
let sendButtonFrame = CGRect(origin: CGPoint(x: leftButtonFrame.maxX + sideInset, y: leftButtonFrame.minY), size: CGSize(width: size.width - leftButtonFrame.maxX - sideInset * 2.0, height: buttonHeight))
let fullButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: buttonOffset - sideInset - buttonHeight), size: CGSize(width: size.width - sideInset * 2.0, height: buttonHeight))
var receiveButtonFrame: CGRect
if let balance = self.balance, balance > 0 {
receiveButtonFrame = leftButtonFrame
self.receiveGramsButtonNode.isHidden = true
self.receiveButtonNode.isHidden = false
self.sendButtonNode.isHidden = false
} else {
receiveButtonFrame = fullButtonFrame
if self.balance == nil {
self.receiveGramsButtonNode.isHidden = true
self.receiveButtonNode.isHidden = true
self.sendButtonNode.isHidden = true
} else {
self.receiveButtonNode.isHidden = false
self.receiveGramsButtonNode.isHidden = false
self.receiveButtonNode.isHidden = true
self.sendButtonNode.isHidden = true
}
}
@ -357,9 +363,12 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
self.refreshNode.isHidden = false
}
transition.updateFrame(node: self.receiveButtonNode, frame: receiveButtonFrame)
transition.updateFrame(node: self.receiveGramsButtonNode, frame: fullButtonFrame)
transition.updateAlpha(node: self.receiveGramsButtonNode, alpha: buttonAlpha)
transition.updateFrame(node: self.receiveButtonNode, frame: leftButtonFrame)
transition.updateAlpha(node: self.receiveButtonNode, alpha: buttonAlpha)
self.receiveButtonNode.updateLayout(width: receiveButtonFrame.width, transition: transition)
self.receiveGramsButtonNode.updateLayout(width: fullButtonFrame.width, transition: transition)
self.receiveButtonNode.updateLayout(width: leftButtonFrame.width, transition: transition)
transition.updateFrame(node: self.sendButtonNode, frame: sendButtonFrame)
transition.updateAlpha(node: self.sendButtonNode, alpha: buttonAlpha)
self.sendButtonNode.updateLayout(width: sendButtonFrame.width, transition: transition)
@ -372,12 +381,16 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
if let result = self.receiveButtonNode.hitTest(self.view.convert(point, to: self.receiveButtonNode.view), with: event) {
return result
}
if let result = self.receiveGramsButtonNode.hitTest(self.view.convert(point, to: self.receiveGramsButtonNode.view), with: event) {
return result
}
return nil
}
func becameReady(animated: Bool) {
if animated {
self.sendButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.receiveGramsButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.receiveButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.balanceNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.balanceSubtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)

View File

@ -242,7 +242,7 @@ func cornersImage(_ theme: WalletTheme, top: Bool, bottom: Bool) -> UIImage? {
func itemListClearInputIcon(_ theme: WalletTheme) -> UIImage? {
return theme.image(WalletThemeResourceKey.itemListClearInputIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: theme.list.inputClearButtonColor)
return generateTintedImage(image: UIImage(bundleImageName: "Wallet/ClearInput"), color: theme.list.inputClearButtonColor)
})
}

View File

@ -71,7 +71,7 @@ public final class WalletSplashScreen: ViewController {
self.walletCreatedPreloadState = nil
}
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Wallet_Navigation_Back, close: self.presentationData.strings.Wallet_Navigation_Close)))
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Wallet_Intro_NotNow, close: self.presentationData.strings.Wallet_Navigation_Close)))
self.statusBar.statusBarStyle = self.presentationData.theme.statusBarStyle
self.navigationPresentation = .modalInLargeLayout
@ -79,9 +79,7 @@ public final class WalletSplashScreen: ViewController {
self.navigationBar?.intrinsicCanTransitionInline = false
switch self.mode {
case .intro:
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Wallet_Intro_NotNow, style: .plain, target: self, action: #selector(self.backPressed)), animated: false)
self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Wallet_Intro_ImportExisting, style: .plain, target: self, action: #selector(self.importPressed)), animated: false)
case let .intro: self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Wallet_Intro_ImportExisting, style: .plain, target: self, action: #selector(self.importPressed)), animated: false)
case let .sending(walletInfo, address, amount, textMessage, randomId, serverSalt):
self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false)
let _ = (self.context.keychain.decrypt(walletInfo.encryptedSecret)

View File

@ -414,12 +414,13 @@ public final class WalletStrings: Equatable {
public var Wallet_Info_RefreshErrorText: String { return self._s[188]! }
public var Wallet_SecureStorageReset_Title: String { return self._s[189]! }
public var Wallet_Receive_CommentHeader: String { return self._s[190]! }
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
public var Wallet_Info_ReceiveGrams: String { return self._s[191]! }
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
}
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)

View File

@ -2248,7 +2248,7 @@ public final class WalletWordCheckScreen: ViewController {
}
private func generateClearIcon(color: UIColor) -> UIImage? {
return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color)
return generateTintedImage(image: UIImage(bundleImageName: "Wallet/ClearInput"), color: color)
}
private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {

View File

@ -77,9 +77,9 @@ public final class WalletWordDisplayScreen: ViewController {
let deltaTime = Date().timeIntervalSince1970 - strongSelf.startTime
let minimalTimeout: Double
#if DEBUG
minimalTimeout = 60.0
minimalTimeout = 5.0
#else
minimalTimeout = 60.0
minimalTimeout = 30.0
#endif
if deltaTime < minimalTimeout {
strongSelf.present(standardTextAlertController(theme: strongSelf.presentationData.theme.alert, title: strongSelf.presentationData.strings.Wallet_Words_NotDoneTitle, text: strongSelf.presentationData.strings.Wallet_Words_NotDoneText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Wallet_Words_NotDoneOk, action: {

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "Clear.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_share.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB