Refactored PasscodeInputFieldNode

This commit is contained in:
Ilya Laktyushin 2019-09-21 02:59:11 +03:00
parent d36c7a9fb2
commit 5c80f423bb
21 changed files with 968 additions and 189 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1980,6 +1980,20 @@
ReferencedContainer = "container:submodules/OpusBinding/OpusBinding.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E66DC04E928346B000000000"
BuildableName = "libPasscodeInputFieldNode.a"
BlueprintName = "PasscodeInputFieldNode"
ReferencedContainer = "container:submodules/PasscodeInputFieldNode/PasscodeInputFieldNode.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"

View File

@ -0,0 +1,17 @@
load("//Config:buck_rule_macros.bzl", "static_library")
static_library(
name = "PasscodeInputFieldNode",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared",
"//submodules/AsyncDisplayKit:AsyncDisplayKit#shared",
"//submodules/Display:Display#shared",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
],
)

View File

@ -0,0 +1,22 @@
<?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>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<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>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>

View File

@ -0,0 +1,401 @@
<?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>archiveVersion</key>
<string>1</string>
<key>classes</key>
<dict>
</dict>
<key>objectVersion</key>
<string>46</string>
<key>objects</key>
<dict>
<key>1DD70E2954723C0500000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeInputFieldNode-Debug.xcconfig</string>
<key>path</key>
<string>../../buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Debug.xcconfig</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
<key>explicitFileType</key>
<string>text.xcconfig</string>
</dict>
<key>1DD70E29E5F5E62F00000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeInputFieldNode-Profile.xcconfig</string>
<key>path</key>
<string>../../buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Profile.xcconfig</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
<key>explicitFileType</key>
<string>text.xcconfig</string>
</dict>
<key>1DD70E29598C919100000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeInputFieldNode-Release.xcconfig</string>
<key>path</key>
<string>../../buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Release.xcconfig</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
<key>explicitFileType</key>
<string>text.xcconfig</string>
</dict>
<key>B401C9792F7F325000000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>Buck (Do Not Modify)</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>1DD70E2954723C0500000000</string>
<string>1DD70E29E5F5E62F00000000</string>
<string>1DD70E29598C919100000000</string>
</array>
</dict>
<key>B401C979B781F65D00000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>Configurations</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>B401C9792F7F325000000000</string>
</array>
</dict>
<key>1DD70E29FF334B1F00000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libDisplay.dylib</string>
<key>path</key>
<string>libDisplay.dylib</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>compiled.mach-o.dylib</string>
</dict>
<key>1DD70E29D65BA68200000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libSwiftSignalKit.dylib</string>
<key>path</key>
<string>libSwiftSignalKit.dylib</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>compiled.mach-o.dylib</string>
</dict>
<key>B401C97968022A5500000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>Frameworks</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>1DD70E29FF334B1F00000000</string>
<string>1DD70E29D65BA68200000000</string>
</array>
</dict>
<key>1DD70E29001F47FB00000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>BUCK</string>
<key>path</key>
<string>BUCK</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
<key>explicitFileType</key>
<string>text.script.python</string>
</dict>
<key>1DD70E290BCAAD5500000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeInputFieldNode.swift</string>
<key>path</key>
<string>Sources/PasscodeInputFieldNode.swift</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>B401C979EAB5339800000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>Sources</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>1DD70E290BCAAD5500000000</string>
</array>
</dict>
<key>B401C979928346B000000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>PasscodeInputFieldNode</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>1DD70E29001F47FB00000000</string>
<string>B401C979EAB5339800000000</string>
</array>
</dict>
<key>1DD70E2989A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libPasscodeInputFieldNode.a</string>
<key>path</key>
<string>libPasscodeInputFieldNode.a</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>B401C979C806358400000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>Products</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>1DD70E2989A0042800000000</string>
</array>
</dict>
<key>B401C979EFB6AC4600000000</key>
<dict>
<key>isa</key>
<string>PBXGroup</string>
<key>name</key>
<string>mainGroup</string>
<key>sourceTree</key>
<string><![CDATA[<group>]]></string>
<key>children</key>
<array>
<string>B401C979B781F65D00000000</string>
<string>B401C97968022A5500000000</string>
<string>B401C979928346B000000000</string>
<string>B401C979C806358400000000</string>
</array>
</dict>
<key>E7A30F040BCAAD5500000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E290BCAAD5500000000</string>
</dict>
<key>1870857F0000000000000000</key>
<dict>
<key>isa</key>
<string>PBXSourcesBuildPhase</string>
<key>files</key>
<array>
<string>E7A30F040BCAAD5500000000</string>
</array>
</dict>
<key>E7A30F04FF334B1F00000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E29FF334B1F00000000</string>
</dict>
<key>E7A30F04D65BA68200000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E29D65BA68200000000</string>
</dict>
<key>FAF5FAC90000000000000000</key>
<dict>
<key>isa</key>
<string>PBXCopyFilesBuildPhase</string>
<key>files</key>
<array>
<string>E7A30F04FF334B1F00000000</string>
<string>E7A30F04D65BA68200000000</string>
</array>
<key>name</key>
<string>Fake Swift Dependencies (Copy Files Phase)</string>
<key>runOnlyForDeploymentPostprocessing</key>
<integer>1</integer>
<key>dstSubfolderSpec</key>
<integer>16</integer>
<key>dstPath</key>
<string></string>
</dict>
<key>4952437303EDA63300000000</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Debug</string>
<key>buildSettings</key>
<dict>
</dict>
<key>baseConfigurationReference</key>
<string>1DD70E2954723C0500000000</string>
</dict>
<key>4952437350C7218900000000</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Profile</string>
<key>buildSettings</key>
<dict>
</dict>
<key>baseConfigurationReference</key>
<string>1DD70E29E5F5E62F00000000</string>
</dict>
<key>49524373A439BFE700000000</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Release</string>
<key>buildSettings</key>
<dict>
</dict>
<key>baseConfigurationReference</key>
<string>1DD70E29598C919100000000</string>
</dict>
<key>218C37090000000000000000</key>
<dict>
<key>isa</key>
<string>XCConfigurationList</string>
<key>buildConfigurations</key>
<array>
<string>4952437303EDA63300000000</string>
<string>4952437350C7218900000000</string>
<string>49524373A439BFE700000000</string>
</array>
<key>defaultConfigurationIsVisible</key>
<false/>
</dict>
<key>E66DC04E928346B000000000</key>
<dict>
<key>isa</key>
<string>PBXNativeTarget</string>
<key>name</key>
<string>PasscodeInputFieldNode</string>
<key>productName</key>
<string>PasscodeInputFieldNode</string>
<key>productReference</key>
<string>1DD70E2989A0042800000000</string>
<key>productType</key>
<string>com.apple.product-type.library.static</string>
<key>dependencies</key>
<array>
</array>
<key>buildPhases</key>
<array>
<string>1870857F0000000000000000</string>
<string>FAF5FAC90000000000000000</string>
</array>
<key>buildConfigurationList</key>
<string>218C37090000000000000000</string>
</dict>
<key>4952437303EDA63300000001</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Debug</string>
<key>buildSettings</key>
<dict>
</dict>
</dict>
<key>4952437350C7218900000001</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Profile</string>
<key>buildSettings</key>
<dict>
</dict>
</dict>
<key>49524373A439BFE700000001</key>
<dict>
<key>isa</key>
<string>XCBuildConfiguration</string>
<key>name</key>
<string>Release</string>
<key>buildSettings</key>
<dict>
</dict>
</dict>
<key>218C37090000000000000001</key>
<dict>
<key>isa</key>
<string>XCConfigurationList</string>
<key>buildConfigurations</key>
<array>
<string>4952437303EDA63300000001</string>
<string>4952437350C7218900000001</string>
<string>49524373A439BFE700000001</string>
</array>
<key>defaultConfigurationIsVisible</key>
<false/>
</dict>
<key>96C84793928346B000000000</key>
<dict>
<key>isa</key>
<string>PBXProject</string>
<key>mainGroup</key>
<string>B401C979EFB6AC4600000000</string>
<key>targets</key>
<array>
<string>E66DC04E928346B000000000</string>
</array>
<key>buildConfigurationList</key>
<string>218C37090000000000000001</string>
<key>compatibilityVersion</key>
<string>Xcode 3.2</string>
<key>attributes</key>
<dict>
<key>LastUpgradeCheck</key>
<string>9999</string>
</dict>
</dict>
</dict>
<key>rootObject</key>
<string>96C84793928346B000000000</string>
</dict>
</plist>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Scheme LastUpgradeVersion="9999" version="1.7"><BuildAction buildImplicitDependencies="YES" parallelizeBuildables="YES"><BuildActionEntries><BuildActionEntry buildForAnalyzing="YES" buildForArchiving="YES" buildForProfiling="YES" buildForRunning="YES" buildForTesting="YES"><BuildableReference BlueprintIdentifier="E66DC04E928346B000000000" BlueprintName="PasscodeInputFieldNode" BuildableIdentifier="primary" BuildableName="libPasscodeInputFieldNode.a" ReferencedContainer="container:PasscodeInputFieldNode.xcodeproj"/></BuildActionEntry></BuildActionEntries></BuildAction><TestAction buildConfiguration="Debug" shouldUseLaunchSchemeArgsEnv="YES"><Testables/></TestAction><LaunchAction buildConfiguration="Debug"/><ProfileAction buildConfiguration="Release"/><AnalyzeAction buildConfiguration="Debug"/><ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"/></Scheme>

View File

@ -0,0 +1,11 @@
#import <UIKit/UIKit.h>
//! Project version number for PasscodeInputFieldNode.
FOUNDATION_EXPORT double PasscodeInputFieldNodeVersionNumber;
//! Project version string for PasscodeInputFieldNode.
FOUNDATION_EXPORT const unsigned char PasscodeInputFieldNodeVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <PasscodeInputFieldNode/PublicHeader.h>

View File

@ -24,19 +24,19 @@ private func generateDotImage(color: UIColor, filled: Bool) -> UIImage? {
})
}
private func generateFieldBackgroundImage(background: PasscodeBackground, frame: CGRect) -> UIImage? {
private func generateFieldBackgroundImage(backgroundImage: UIImage, backgroundSize: CGSize, frame: CGRect) -> UIImage? {
return generateImage(frame.size, contextGenerator: { size, context in
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
let relativeFrame = CGRect(x: -frame.minX, y: frame.minY - background.size.height + frame.size.height
, width: background.size.width, height: background.size.height)
let relativeFrame = CGRect(x: -frame.minX, y: frame.minY - backgroundSize.height + frame.size.height
, width: backgroundSize.width, height: backgroundSize.height)
let path = UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height), cornerRadius: 6.0)
context.addPath(path.cgPath)
context.clip()
context.draw(background.foregroundImage.cgImage!, in: relativeFrame)
context.draw(backgroundImage.cgImage!, in: relativeFrame)
context.setBlendMode(.clear)
context.setFillColor(UIColor.clear.cgColor)
@ -128,8 +128,8 @@ private class PasscodeEntryDotNode: ASImageNode {
}
}
public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate {
private var background: PasscodeBackground?
public final class PasscodeInputFieldNode: ASDisplayNode, UITextFieldDelegate {
private var background: (UIImage, CGSize)?
private var color: UIColor
private var accentColor: UIColor
private var fieldType: PasscodeEntryFieldType
@ -139,7 +139,7 @@ public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelega
private let borderNode: ASImageNode
private let dotNodes: [PasscodeEntryDotNode]
private var validLayout: PasscodeLayout?
private var validLayout: (ContainerViewLayout, CGFloat)?
public var complete: ((String) -> Void)?
@ -202,15 +202,15 @@ public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelega
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
if let validLayout = self.validLayout {
let _ = self.updateLayout(layout: validLayout, transition: animated ? .animated(duration: 0.25, curve: .easeInOut) : .immediate)
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: animated ? .animated(duration: 0.25, curve: .easeInOut) : .immediate)
}
}
func updateBackground(_ background: PasscodeBackground) {
self.background = background
if let validLayout = self.validLayout {
let _ = self.updateLayout(layout: validLayout, transition: .immediate)
func updateBackground(_ image: UIImage, size: CGSize) {
self.background = (image, size)
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: .immediate)
}
}
@ -302,13 +302,13 @@ public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelega
self.textFieldNode.textField.text = ""
}
self.fieldType = fieldType
if let validLayout = self.validLayout {
let _ = self.updateLayout(layout: validLayout, transition: .immediate)
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: .immediate)
}
}
public func updateLayout(layout: PasscodeLayout, transition: ContainedViewLayoutTransition) -> CGRect {
self.validLayout = layout
public func updateLayout(layout: ContainerViewLayout, topOffset: CGFloat, transition: ContainedViewLayoutTransition) -> CGRect {
self.validLayout = (layout, topOffset)
let fieldAlpha: CGFloat
switch self.fieldType {
@ -321,7 +321,7 @@ public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelega
transition.updateAlpha(node: self.textFieldNode, alpha: fieldAlpha)
transition.updateAlpha(node: self.borderNode, alpha: fieldAlpha)
let origin = CGPoint(x: floor((layout.layout.size.width - dotDiameter * 6 - dotSpacing * 5) / 2.0), y: layout.inputFieldOffset)
let origin = CGPoint(x: floor((layout.size.width - dotDiameter * 6 - dotSpacing * 5) / 2.0), y: topOffset)
for i in 0 ..< self.dotNodes.count {
let node = self.dotNodes[i]
let dotAlpha: CGFloat
@ -343,11 +343,11 @@ public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelega
if !self.useCustomNumpad {
inset = 16.0
}
let fieldFrame = CGRect(x: inset, y: origin.y, width: layout.layout.size.width - inset * 2.0, height: fieldHeight)
let fieldFrame = CGRect(x: inset, y: origin.y, width: layout.size.width - inset * 2.0, height: fieldHeight)
transition.updateFrame(node: self.borderNode, frame: fieldFrame)
transition.updateFrame(node: self.textFieldNode, frame: fieldFrame.insetBy(dx: 13.0, dy: 0.0))
if let background = self.background {
self.borderNode.image = generateFieldBackgroundImage(background: background, frame: fieldFrame)
if let (backgroundImage, backgroundSize) = self.background {
self.borderNode.image = generateFieldBackgroundImage(backgroundImage: backgroundImage, backgroundSize: backgroundSize, frame: fieldFrame)
}
return fieldFrame

View File

@ -19,6 +19,7 @@ static_library(
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/ImageBlur:ImageBlur",
"//submodules/AppBundle:AppBundle",
"//submodules/PasscodeInputFieldNode:PasscodeInputFieldNode",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -169,6 +169,19 @@
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E2989A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libPasscodeInputFieldNode.a</string>
<key>path</key>
<string>libPasscodeInputFieldNode.a</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E290F1A3C6400000000</key>
<dict>
<key>isa</key>
@ -329,6 +342,7 @@
<string>1DD70E29A889192100000000</string>
<string>1DD70E29CE34063500000000</string>
<string>1DD70E2936DE2CF900000000</string>
<string>1DD70E2989A0042800000000</string>
<string>1DD70E290F1A3C6400000000</string>
<string>1DD70E29DB6520C800000000</string>
<string>1DD70E29D65BA68200000000</string>
@ -388,17 +402,6 @@
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E293E85462B00000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeEntryInputFieldNode.swift</string>
<key>path</key>
<string>Sources/PasscodeEntryInputFieldNode.swift</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E293E99570200000000</key>
<dict>
<key>isa</key>
@ -421,6 +424,17 @@
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E290BCAAD5500000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>PasscodeInputFieldNode.swift</string>
<key>path</key>
<string>Sources/PasscodeInputFieldNode.swift</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E299AE87B0D00000000</key>
<dict>
<key>isa</key>
@ -478,9 +492,9 @@
<string>1DD70E2944FAB31100000000</string>
<string>1DD70E298C702AD500000000</string>
<string>1DD70E297F6C137700000000</string>
<string>1DD70E293E85462B00000000</string>
<string>1DD70E293E99570200000000</string>
<string>1DD70E29A75DC52700000000</string>
<string>1DD70E290BCAAD5500000000</string>
<string>1DD70E299AE87B0D00000000</string>
<string>1DD70E29E2D8E4C900000000</string>
<string>1DD70E298FD9E6E000000000</string>
@ -564,13 +578,6 @@
<key>fileRef</key>
<string>1DD70E297F6C137700000000</string>
</dict>
<key>E7A30F043E85462B00000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E293E85462B00000000</string>
</dict>
<key>E7A30F043E99570200000000</key>
<dict>
<key>isa</key>
@ -585,6 +592,13 @@
<key>fileRef</key>
<string>1DD70E29A75DC52700000000</string>
</dict>
<key>E7A30F040BCAAD5500000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E290BCAAD5500000000</string>
</dict>
<key>E7A30F049AE87B0D00000000</key>
<dict>
<key>isa</key>
@ -622,9 +636,9 @@
<string>E7A30F0444FAB31100000000</string>
<string>E7A30F048C702AD500000000</string>
<string>E7A30F047F6C137700000000</string>
<string>E7A30F043E85462B00000000</string>
<string>E7A30F043E99570200000000</string>
<string>E7A30F04A75DC52700000000</string>
<string>E7A30F040BCAAD5500000000</string>
<string>E7A30F049AE87B0D00000000</string>
<string>E7A30F04E2D8E4C900000000</string>
<string>E7A30F048FD9E6E000000000</string>
@ -757,6 +771,13 @@
<key>fileRef</key>
<string>1DD70E29A889192100000000</string>
</dict>
<key>E7A30F0489A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E2989A0042800000000</string>
</dict>
<key>FAF5FAC90000000000000000</key>
<dict>
<key>isa</key>
@ -781,6 +802,7 @@
<string>E7A30F049D2580DA00000000</string>
<string>E7A30F04D6F14E1000000000</string>
<string>E7A30F04A889192100000000</string>
<string>E7A30F0489A0042800000000</string>
</array>
<key>name</key>
<string>Fake Swift Dependencies (Copy Files Phase)</string>

View File

@ -9,6 +9,7 @@ import TelegramPresentationData
import AccountContext
import LocalAuth
import AppBundle
import PasscodeInputFieldNode
private let titleFont = Font.regular(20.0)
private let subtitleFont = Font.regular(15.0)
@ -29,7 +30,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
private let backgroundNode: ASImageNode
private let iconNode: PasscodeLockIconNode
private let titleNode: PasscodeEntryLabelNode
private let inputFieldNode: PasscodeEntryInputFieldNode
private let inputFieldNode: PasscodeInputFieldNode
private let subtitleNode: PasscodeEntryLabelNode
private let keyboardNode: PasscodeEntryKeyboardNode
private let cancelButtonNode: HighlightableButtonNode
@ -62,7 +63,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
self.iconNode = PasscodeLockIconNode()
self.titleNode = PasscodeEntryLabelNode()
self.inputFieldNode = PasscodeEntryInputFieldNode(color: .white, accentColor: .white, fieldType: passcodeType, keyboardAppearance: .dark, useCustomNumpad: true)
self.inputFieldNode = PasscodeInputFieldNode(color: .white, accentColor: .white, fieldType: passcodeType, keyboardAppearance: .dark, useCustomNumpad: true)
self.subtitleNode = PasscodeEntryLabelNode()
self.keyboardNode = PasscodeEntryKeyboardNode()
self.cancelButtonNode = HighlightableButtonNode()
@ -188,7 +189,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
if let background = self.background {
self.backgroundNode.image = background.backgroundImage
self.keyboardNode.updateBackground(background)
self.inputFieldNode.updateBackground(background)
self.inputFieldNode.updateBackground(background.foregroundImage, size: background.size)
}
}
@ -346,7 +347,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
let passcodeLayout = PasscodeLayout(layout: layout)
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout, transition: transition)
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout.layout, topOffset: passcodeLayout.inputFieldOffset, transition: transition)
transition.updateFrame(node: self.inputFieldNode, frame: CGRect(origin: CGPoint(), size: layout.size))
let titleSize = self.titleNode.updateLayout(layout: layout, transition: transition)

View File

@ -0,0 +1,382 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
private let dotDiameter: CGFloat = 13.0
private let dotSpacing: CGFloat = 24.0
private let fieldHeight: CGFloat = 38.0
private func generateDotImage(color: UIColor, filled: Bool) -> UIImage? {
return generateImage(CGSize(width: dotDiameter, height: dotDiameter), contextGenerator: { size, context in
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
if filled {
context.setFillColor(color.cgColor)
context.fillEllipse(in: bounds)
} else {
context.setStrokeColor(color.cgColor)
context.setLineWidth(1.0)
context.strokeEllipse(in: bounds.insetBy(dx: 0.5, dy: 0.5))
}
})
}
private func generateFieldBackgroundImage(backgroundImage: UIImage, backgroundSize: CGSize, frame: CGRect) -> UIImage? {
return generateImage(frame.size, contextGenerator: { size, context in
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
let relativeFrame = CGRect(x: -frame.minX, y: frame.minY - backgroundSize.height + frame.size.height
, width: backgroundSize.width, height: backgroundSize.height)
let path = UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height), cornerRadius: 6.0)
context.addPath(path.cgPath)
context.clip()
context.draw(backgroundImage.cgImage!, in: relativeFrame)
context.setBlendMode(.clear)
context.setFillColor(UIColor.clear.cgColor)
let innerPath = UIBezierPath(roundedRect: CGRect(x: 1.0, y: 1.0, width: size.width - 2.0, height: size.height - 2.0), cornerRadius: 6.0)
context.addPath(innerPath.cgPath)
context.fillPath()
})
}
private let validDigitsSet: CharacterSet = {
return CharacterSet(charactersIn: "0".unicodeScalars.first! ... "9".unicodeScalars.first!)
}()
public enum PasscodeEntryFieldType {
case digits6
case digits4
case alphanumeric
public var maxLength: Int? {
switch self {
case .digits6:
return 6
case .digits4:
return 4
case .alphanumeric:
return nil
}
}
public var allowedCharacters: CharacterSet? {
switch self {
case .digits6, .digits4:
return validDigitsSet
case .alphanumeric:
return nil
}
}
public var keyboardType: UIKeyboardType {
switch self {
case .digits6, .digits4:
if #available(iOS 10.0, *) {
return .asciiCapableNumberPad
} else {
return .numberPad
}
case .alphanumeric:
return .default
}
}
}
private class PasscodeEntryInputView: UIView {
}
private class PasscodeEntryDotNode: ASImageNode {
private let regularImage: UIImage
private let filledImage: UIImage
private var currentImage: UIImage
init(color: UIColor) {
self.regularImage = generateDotImage(color: color, filled: false)!
self.filledImage = generateDotImage(color: color, filled: true)!
self.currentImage = self.regularImage
super.init()
self.image = self.currentImage
}
func updateState(filled: Bool, animated: Bool = false, delay: Double = 0.0) {
let image = filled ? self.filledImage : self.regularImage
if self.currentImage !== image {
let currentContents = self.layer.contents
self.layer.removeAnimation(forKey: "contents")
if let currentContents = currentContents, animated {
self.layer.animate(from: currentContents as AnyObject, to: image.cgImage!, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: image === self.regularImage ? 0.25 : 0.05, delay: delay, removeOnCompletion: false, completion: { finished in
if finished {
self.image = image
}
})
} else {
self.image = image
}
self.currentImage = image
}
}
}
public final class PasscodeInputFieldNode: ASDisplayNode, UITextFieldDelegate {
private var background: (UIImage, CGSize)?
private var color: UIColor
private var accentColor: UIColor
private var fieldType: PasscodeEntryFieldType
private let useCustomNumpad: Bool
private let textFieldNode: TextFieldNode
private let borderNode: ASImageNode
private let dotNodes: [PasscodeEntryDotNode]
private var validLayout: (ContainerViewLayout, CGFloat)?
public var complete: ((String) -> Void)?
public var text: String {
return self.textFieldNode.textField.text ?? ""
}
public var keyboardAppearance: UIKeyboardAppearance {
didSet {
self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance
}
}
public init(color: UIColor, accentColor: UIColor, fieldType: PasscodeEntryFieldType, keyboardAppearance: UIKeyboardAppearance, useCustomNumpad: Bool = false) {
self.color = color
self.accentColor = accentColor
self.fieldType = fieldType
self.keyboardAppearance = keyboardAppearance
self.useCustomNumpad = useCustomNumpad
self.textFieldNode = TextFieldNode()
self.borderNode = ASImageNode()
self.dotNodes = (0 ..< 6).map { _ in PasscodeEntryDotNode(color: color) }
super.init()
self.isUserInteractionEnabled = false
for node in self.dotNodes {
self.addSubnode(node)
}
self.addSubnode(self.textFieldNode)
self.addSubnode(self.borderNode)
}
override public func didLoad() {
super.didLoad()
self.textFieldNode.textField.isSecureTextEntry = true
self.textFieldNode.textField.textColor = self.color
self.textFieldNode.textField.delegate = self
self.textFieldNode.textField.returnKeyType = .done
self.textFieldNode.textField.tintColor = self.accentColor
self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
self.textFieldNode.textField.tintColor = self.accentColor
if self.useCustomNumpad {
switch self.fieldType {
case .digits6, .digits4:
self.textFieldNode.textField.inputView = PasscodeEntryInputView()
case .alphanumeric:
break
}
}
}
func updateFieldType(_ fieldType: PasscodeEntryFieldType, animated: Bool) {
self.fieldType = fieldType
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: animated ? .animated(duration: 0.25, curve: .easeInOut) : .immediate)
}
}
func updateBackground(_ image: UIImage, size: CGSize) {
self.background = (image, size)
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: .immediate)
}
}
public func activateInput() {
self.textFieldNode.textField.becomeFirstResponder()
}
func animateIn() {
switch self.fieldType {
case .digits6, .digits4:
for node in self.dotNodes {
node.layer.animateScale(from: 0.0001, to: 1.0, duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
}
case .alphanumeric:
self.textFieldNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
self.borderNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
}
}
func animateSuccess() {
switch self.fieldType {
case .digits6, .digits4:
var delay: Double = 0.0
for node in self.dotNodes {
node.updateState(filled: true, animated: true, delay: delay)
delay += 0.01
}
case .alphanumeric:
if (self.textFieldNode.textField.text ?? "").isEmpty {
self.textFieldNode.textField.text = "passwordpassword"
}
}
}
public func reset(animated: Bool = true) {
var delay: Double = 0.0
for node in self.dotNodes.reversed() {
if node.alpha < 1.0 {
continue
}
node.updateState(filled: false, animated: animated, delay: delay)
delay += 0.05
}
self.textFieldNode.textField.text = ""
}
func append(_ string: String) {
var text = (self.textFieldNode.textField.text ?? "") + string
let maxLength = self.fieldType.maxLength
if let maxLength = maxLength, text.count > maxLength {
return
}
self.textFieldNode.textField.text = text
text = self.textFieldNode.textField.text ?? "" + string
self.updateDots(count: text.count, animated: false)
if let maxLength = maxLength, text.count == maxLength {
Queue.mainQueue().after(0.2) {
self.complete?(text)
}
}
}
func delete() {
var text = self.textFieldNode.textField.text ?? ""
guard !text.isEmpty else {
return
}
text = String(text[text.startIndex ..< text.index(text.endIndex, offsetBy: -1)])
self.textFieldNode.textField.text = text
self.updateDots(count: text.count, animated: true)
}
func updateDots(count: Int, animated: Bool) {
var i = -1
for node in self.dotNodes {
if node.alpha < 1.0 {
continue
}
i += 1
node.updateState(filled: i < count, animated: animated)
}
}
public func update(fieldType: PasscodeEntryFieldType) {
if fieldType != self.fieldType {
self.textFieldNode.textField.text = ""
}
self.fieldType = fieldType
if let (layout, topOffset) = self.validLayout {
let _ = self.updateLayout(layout: layout, topOffset: topOffset, transition: .immediate)
}
}
public func updateLayout(layout: ContainerViewLayout, topOffset: CGFloat, transition: ContainedViewLayoutTransition) -> CGRect {
self.validLayout = (layout, topOffset)
let fieldAlpha: CGFloat
switch self.fieldType {
case .digits6, .digits4:
fieldAlpha = 0.0
case .alphanumeric:
fieldAlpha = 1.0
}
transition.updateAlpha(node: self.textFieldNode, alpha: fieldAlpha)
transition.updateAlpha(node: self.borderNode, alpha: fieldAlpha)
let origin = CGPoint(x: floor((layout.size.width - dotDiameter * 6 - dotSpacing * 5) / 2.0), y: topOffset)
for i in 0 ..< self.dotNodes.count {
let node = self.dotNodes[i]
let dotAlpha: CGFloat
switch self.fieldType {
case .digits6:
dotAlpha = 1.0
case .digits4:
dotAlpha = (i > 0 && i < self.dotNodes.count - 1) ? 1.0 : 0.0
case .alphanumeric:
dotAlpha = 0.0
}
transition.updateAlpha(node: node, alpha: dotAlpha)
let dotFrame = CGRect(x: origin.x + CGFloat(i) * (dotDiameter + dotSpacing), y: origin.y, width: dotDiameter, height: dotDiameter)
transition.updateFrame(node: node, frame: dotFrame)
}
var inset: CGFloat = 50.0
if !self.useCustomNumpad {
inset = 16.0
}
let fieldFrame = CGRect(x: inset, y: origin.y, width: layout.size.width - inset * 2.0, height: fieldHeight)
transition.updateFrame(node: self.borderNode, frame: fieldFrame)
transition.updateFrame(node: self.textFieldNode, frame: fieldFrame.insetBy(dx: 13.0, dy: 0.0))
if let (backgroundImage, backgroundSize) = self.background {
self.borderNode.image = generateFieldBackgroundImage(backgroundImage: backgroundImage, backgroundSize: backgroundSize, frame: fieldFrame)
}
return fieldFrame
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentText = textField.text ?? ""
let text = (currentText as NSString).replacingCharacters(in: range, with: string)
if let maxLength = self.fieldType.maxLength, text.count > maxLength {
return false
}
if let allowedCharacters = self.fieldType.allowedCharacters, let _ = text.rangeOfCharacter(from: allowedCharacters.inverted) {
return false
}
self.updateDots(count: text.count, animated: text.count < currentText.count)
if string == "\n" {
Queue.mainQueue().after(0.2) {
self.complete?(currentText)
}
return false
}
if let maxLength = self.fieldType.maxLength, text.count == maxLength {
Queue.mainQueue().after(0.2) {
self.complete?(text)
}
}
return true
}
}

View File

@ -4,6 +4,7 @@ import AsyncDisplayKit
import Display
import TelegramCore
import TelegramPresentationData
import PasscodeInputFieldNode
enum PasscodeSetupInitialState {
case createPasscode
@ -36,7 +37,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
private let titleNode: ASTextNode
private let subtitleNode: ASTextNode
private let inputFieldNode: PasscodeEntryInputFieldNode
private let inputFieldNode: PasscodeInputFieldNode
private let inputFieldBackgroundNode: ASImageNode
private let modeButtonNode: HighlightableButtonNode
@ -82,7 +83,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
passcodeType = .digits6
}
self.inputFieldNode = PasscodeEntryInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: passcodeType, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance)
self.inputFieldNode = PasscodeInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: passcodeType, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance)
self.inputFieldBackgroundNode = ASImageNode()
self.inputFieldBackgroundNode.alpha = passcodeType == .alphanumeric ? 1.0 : 0.0
self.inputFieldBackgroundNode.contentMode = .scaleToFill
@ -145,8 +146,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode {
self.wrapperNode.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height)
let passcodeLayout = PasscodeLayout(layout: layout, titleOffset: 0.0, subtitleOffset: 0.0, inputFieldOffset: floor(insets.top + navigationBarHeight + (layout.size.height - navigationBarHeight - insets.top - insets.bottom - 24.0) / 2.0))
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout, transition: transition)
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: layout, topOffset: floor(insets.top + navigationBarHeight + (layout.size.height - navigationBarHeight - insets.top - insets.bottom - 24.0) / 2.0), transition: transition)
transition.updateFrame(node: self.inputFieldNode, frame: CGRect(origin: CGPoint(), size: layout.size))
transition.updateFrame(node: self.inputFieldBackgroundNode, frame: CGRect(x: 0.0, y: inputFieldFrame.minY - 6.0, width: layout.size.width, height: 48.0))

View File

@ -832,6 +832,19 @@
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E2989A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libPasscodeInputFieldNode.a</string>
<key>path</key>
<string>libPasscodeInputFieldNode.a</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E29D0DBC52A00000000</key>
<dict>
<key>isa</key>
@ -1602,6 +1615,7 @@
<string>1DD70E2937C1167400000000</string>
<string>1DD70E29AF00DC4900000000</string>
<string>1DD70E29BBAF750C00000000</string>
<string>1DD70E2989A0042800000000</string>
<string>1DD70E29D0DBC52A00000000</string>
<string>1DD70E29300245BE00000000</string>
<string>1DD70E299856EB2400000000</string>
@ -4691,6 +4705,13 @@
<key>fileRef</key>
<string>1DD70E2937C1167400000000</string>
</dict>
<key>E7A30F0489A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E2989A0042800000000</string>
</dict>
<key>E7A30F04D0DBC52A00000000</key>
<dict>
<key>isa</key>
@ -4899,6 +4920,7 @@
<string>E7A30F04A889192100000000</string>
<string>E7A30F04A3994F2C00000000</string>
<string>E7A30F0437C1167400000000</string>
<string>E7A30F0489A0042800000000</string>
<string>E7A30F04D0DBC52A00000000</string>
<string>E7A30F0479E58A0000000000</string>
<string>E7A30F049856EB2400000000</string>

View File

@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Test.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

View File

@ -16,16 +16,16 @@ static_library(
"//submodules/AppBundle:AppBundle",
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
"//submodules/ItemListUI:ItemListUI",
"//submodules/AccountContext:AccountContext",
"//submodules/UndoUI:UndoUI",
"//submodules/AlertUI:AlertUI",
"//submodules/AccountContext:AccountContext",
"//submodules/UndoUI:UndoUI",
"//submodules/AlertUI:AlertUI",
"//submodules/TextFormat:TextFormat",
"//submodules/Camera:Camera",
"//submodules/ShareController:ShareController",
"//submodules/PasscodeUI:PasscodeUI",
"//submodules/PasscodeInputFieldNode:PasscodeInputFieldNode",
"//submodules/QrCode:QrCode",
"//submodules/MergeLists:MergeLists",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/MergeLists:MergeLists",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -10,7 +10,7 @@ import TelegramCore
import AnimationUI
import SwiftSignalKit
import OverlayStatusController
import PasscodeUI
import PasscodeInputFieldNode
public enum WalletPasscodeMode {
case setup
@ -118,7 +118,7 @@ private final class WalletPasscodeScreenNode: ViewControllerTracingNode {
private let titleNode: ImmediateTextNode
private let biometricsActionTitleNode: ImmediateTextNode
private let biometricsActionButtonNode: HighlightTrackingButtonNode
private let inputFieldNode: PasscodeEntryInputFieldNode
private let inputFieldNode: PasscodeInputFieldNode
private let hapticFeedback = HapticFeedback()
@ -154,7 +154,7 @@ private final class WalletPasscodeScreenNode: ViewControllerTracingNode {
self.biometricsActionButtonNode = HighlightTrackingButtonNode()
self.inputFieldNode = PasscodeEntryInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: .digits4, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance)
self.inputFieldNode = PasscodeInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: .digits4, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance)
super.init()
@ -221,8 +221,7 @@ private final class WalletPasscodeScreenNode: ViewControllerTracingNode {
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
let passcodeLayout = PasscodeLayout(layout: layout, titleOffset: 0.0, subtitleOffset: 0.0, inputFieldOffset: titleFrame.maxY + titleSpacing)
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout, transition: transition)
let inputFieldFrame = self.inputFieldNode.updateLayout(layout: layout, topOffset: titleFrame.maxY + titleSpacing, transition: transition)
transition.updateFrame(node: self.inputFieldNode, frame: CGRect(origin: CGPoint(), size: layout.size))
let minimalBottomInset: CGFloat = 60.0

View File

@ -56,11 +56,6 @@ public final class WalletQrScanScreen: ViewController {
private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
private var presentationData: PresentationData
private let navigationBackgroundNode: ASDisplayNode
private let navigationSeparatorNode: ASDisplayNode
private let navigationTitleNode: ImmediateTextNode
private let scrollNode: ASScrollNode
private let iconNode: ASImageNode
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
@ -69,23 +64,9 @@ private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollV
init(presentationData: PresentationData) {
self.presentationData = presentationData
self.navigationBackgroundNode = ASDisplayNode()
self.navigationBackgroundNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.backgroundColor
self.navigationBackgroundNode.alpha = 0.0
self.navigationSeparatorNode = ASDisplayNode()
self.navigationSeparatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
self.scrollNode = ASScrollNode()
self.iconNode = ASImageNode()
self.iconNode.displayWithoutProcessing = true
self.iconNode.displaysAsynchronously = false
let title: String = "24 Secret Words"
let text: String = "Write down these 24 words in the correct order and store them in a secret place.\n\nUse these secret words to restore access to your wallet if you lose your passcode or Telegram account."
let buttonText: String = "Done"
self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/WordsDisplayIcon")
let title: String = ""
let text: String = ""
self.titleNode = ImmediateTextNode()
self.titleNode.displaysAsynchronously = false
@ -93,12 +74,6 @@ private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollV
self.titleNode.maximumNumberOfLines = 0
self.titleNode.textAlignment = .center
self.navigationTitleNode = ImmediateTextNode()
self.navigationTitleNode.displaysAsynchronously = false
self.navigationTitleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
self.navigationTitleNode.maximumNumberOfLines = 0
self.navigationTitleNode.textAlignment = .center
self.textNode = ImmediateTextNode()
self.textNode.displaysAsynchronously = false
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
@ -110,75 +85,29 @@ private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollV
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
self.addSubnode(self.scrollNode)
self.scrollNode.addSubnode(self.iconNode)
self.scrollNode.addSubnode(self.titleNode)
self.scrollNode.addSubnode(self.textNode)
self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode)
self.navigationBackgroundNode.addSubnode(self.navigationTitleNode)
self.addSubnode(self.navigationBackgroundNode)
}
override func didLoad() {
super.didLoad()
self.scrollNode.view.alwaysBounceVertical = false
self.scrollNode.view.showsVerticalScrollIndicator = false
self.scrollNode.view.showsHorizontalScrollIndicator = false
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
self.scrollNode.view.contentInsetAdjustmentBehavior = .never
}
self.scrollNode.view.delegate = self
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let navigationHeight = self.navigationHeight ?? 0.0
let alpha: CGFloat = scrollView.contentOffset.y >= (self.titleNode.frame.maxY - navigationHeight) ? 1.0 : 0.0
if self.navigationBackgroundNode.alpha != alpha {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.12, curve: .easeInOut)
transition.updateAlpha(node: self.navigationBackgroundNode, alpha: alpha, beginWithCurrentState: true)
}
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
}
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
self.navigationHeight = navigationHeight
let sideInset: CGFloat = 32.0
let buttonSideInset: CGFloat = 48.0
let iconSpacing: CGFloat = 5.0
let titleSpacing: CGFloat = 19.0
let textSpacing: CGFloat = 37.0
let buttonHeight: CGFloat = 50.0
let buttonSpacing: CGFloat = 45.0
let wordSpacing: CGFloat = 12.0
let indexSpacing: CGFloat = 4.0
transition.updateFrame(node: self.navigationBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: navigationHeight)))
transition.updateFrame(node: self.navigationSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size))
let iconSize = self.iconNode.image?.size ?? CGSize(width: 50.0, height: 50.0)
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
var contentHeight: CGFloat = 0.0
let contentVerticalOrigin = navigationHeight + 10.0
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize)
transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame)
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: contentVerticalOrigin), size: titleSize)
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
transition.updateFrameAdditive(node: self.navigationTitleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - navigationTitleSize.width) / 2.0), y: navigationHeight - 44.0 + floor((44.0 - navigationTitleSize.height) / 2.0)), size: navigationTitleSize))
contentHeight = textFrame.maxY + textSpacing
}
}

View File

@ -299,19 +299,6 @@
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E29A889192100000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libLocalAuth.a</string>
<key>path</key>
<string>libLocalAuth.a</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E29CE34063500000000</key>
<dict>
<key>isa</key>
@ -364,14 +351,14 @@
<key>explicitFileType</key>
<string>archive.ar</string>
</dict>
<key>1DD70E29D0DBC52A00000000</key>
<key>1DD70E2989A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>libPasscodeUI.a</string>
<string>libPasscodeInputFieldNode.a</string>
<key>path</key>
<string>libPasscodeUI.a</string>
<string>libPasscodeInputFieldNode.a</string>
<key>sourceTree</key>
<string>BUILT_PRODUCTS_DIR</string>
<key>explicitFileType</key>
@ -768,12 +755,11 @@
<string>1DD70E29D6F14E1000000000</string>
<string>1DD70E295A26607D00000000</string>
<string>1DD70E29AC43662400000000</string>
<string>1DD70E29A889192100000000</string>
<string>1DD70E29CE34063500000000</string>
<string>1DD70E2936DE2CF900000000</string>
<string>1DD70E29C37F741500000000</string>
<string>1DD70E29BBAF750C00000000</string>
<string>1DD70E29D0DBC52A00000000</string>
<string>1DD70E2989A0042800000000</string>
<string>1DD70E29928D142900000000</string>
<string>1DD70E29D233F68C00000000</string>
<string>1DD70E290F1A3C6400000000</string>
@ -1363,19 +1349,12 @@
<key>fileRef</key>
<string>1DD70E29BBAF750C00000000</string>
</dict>
<key>E7A30F04A889192100000000</key>
<key>E7A30F0489A0042800000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E29A889192100000000</string>
</dict>
<key>E7A30F04D0DBC52A00000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E29D0DBC52A00000000</string>
<string>1DD70E2989A0042800000000</string>
</dict>
<key>E7A30F04AA32BBC600000000</key>
<dict>
@ -1546,8 +1525,7 @@
<string>E7A30F0425BBFEEE00000000</string>
<string>E7A30F045A26607D00000000</string>
<string>E7A30F04BBAF750C00000000</string>
<string>E7A30F04A889192100000000</string>
<string>E7A30F04D0DBC52A00000000</string>
<string>E7A30F0489A0042800000000</string>
<string>E7A30F04AA32BBC600000000</string>
<string>E7A30F04A54A195300000000</string>
<string>E7A30F041E16CC6C00000000</string>