2019-12-06 06:42:28 +01:00
2019-12-09 02:33:40 +01:00
final class RegisterVC : UIViewController {
2019-12-06 06:42:28 +01:00
private var seed : Data ! { didSet { updateKeyPair ( ) } }
private var keyPair : ECKeyPair ! { didSet { updatePublicKeyLabel ( ) } }
// MARK: C o m p o n e n t s
private lazy var publicKeyLabel : UILabel = {
let result = UILabel ( )
result . textColor = Colors . text
2020-01-17 05:53:56 +01:00
result . font = Fonts . spaceMono ( ofSize : isSmallScreen ? Values . mediumFontSize : Values . largeFontSize )
2019-12-06 06:42:28 +01:00
result . numberOfLines = 0
result . lineBreakMode = . byCharWrapping
return result
} ( )
private lazy var copyPublicKeyButton : Button = {
let result = Button ( style : . prominentOutline , size : . large )
2019-12-13 05:02:05 +01:00
result . setTitle ( NSLocalizedString ( " Copy " , comment : " " ) , for : UIControl . State . normal )
2019-12-06 06:42:28 +01:00
result . addTarget ( self , action : #selector ( copyPublicKey ) , for : UIControl . Event . touchUpInside )
return result
} ( )
2019-12-09 00:27:01 +01:00
private lazy var legalLabel : UILabel = {
let result = UILabel ( )
result . textColor = Colors . text
result . font = . systemFont ( ofSize : Values . verySmallFontSize )
let text = " By using this service, you agree to our Terms and Conditions and Privacy Statement "
let attributedText = NSMutableAttributedString ( string : text )
attributedText . addAttribute ( . font , value : UIFont . boldSystemFont ( ofSize : Values . verySmallFontSize ) , range : ( text as NSString ) . range ( of : " Terms and Conditions " ) )
attributedText . addAttribute ( . font , value : UIFont . boldSystemFont ( ofSize : Values . verySmallFontSize ) , range : ( text as NSString ) . range ( of : " Privacy Statement " ) )
result . attributedText = attributedText
result . numberOfLines = 0
result . textAlignment = . center
result . lineBreakMode = . byWordWrapping
return result
} ( )
2019-12-06 06:42:28 +01:00
// MARK: S e t t i n g s
override var preferredStatusBarStyle : UIStatusBarStyle { return . lightContent }
// MARK: L i f e c y c l e
override func viewDidLoad ( ) {
// S e t g r a d i e n t b a c k g r o u n d
view . backgroundColor = . clear
let gradient = Gradients . defaultLokiBackground
view . setGradient ( gradient )
// S e t u p n a v i g a t i o n b a r
let navigationBar = navigationController ! . navigationBar
navigationBar . setBackgroundImage ( UIImage ( ) , for : UIBarMetrics . default )
navigationBar . shadowImage = UIImage ( )
navigationBar . isTranslucent = false
navigationBar . barTintColor = Colors . navigationBarBackground
// S e t u p l o g o i m a g e v i e w
let logoImageView = UIImageView ( )
2019-12-17 18:04:31 +01:00
logoImageView . image = # imageLiteral ( resourceName : " Session " )
2019-12-06 06:42:28 +01:00
logoImageView . contentMode = . scaleAspectFit
logoImageView . set ( . width , to : 32 )
logoImageView . set ( . height , to : 32 )
navigationItem . titleView = logoImageView
// S e t u p t i t l e l a b e l
let titleLabel = UILabel ( )
titleLabel . textColor = Colors . text
2020-01-17 05:53:56 +01:00
titleLabel . font = . boldSystemFont ( ofSize : isSmallScreen ? Values . largeFontSize : Values . veryLargeFontSize )
2019-12-17 18:04:31 +01:00
titleLabel . text = NSLocalizedString ( " Say hello to your Session ID " , comment : " " )
2019-12-06 06:42:28 +01:00
titleLabel . numberOfLines = 0
titleLabel . lineBreakMode = . byWordWrapping
// S e t u p e x p l a n a t i o n l a b e l
let explanationLabel = UILabel ( )
explanationLabel . textColor = Colors . text
explanationLabel . font = . systemFont ( ofSize : Values . smallFontSize )
2019-12-17 18:04:31 +01:00
explanationLabel . text = NSLocalizedString ( " Your Session ID is the unique address that people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design. " , comment : " " )
2019-12-06 06:42:28 +01:00
explanationLabel . numberOfLines = 0
explanationLabel . lineBreakMode = . byWordWrapping
// S e t u p p u b l i c k e y l a b e l c o n t a i n e r
let publicKeyLabelContainer = UIView ( )
publicKeyLabelContainer . addSubview ( publicKeyLabel )
publicKeyLabel . pin ( to : publicKeyLabelContainer , withInset : Values . mediumSpacing )
publicKeyLabelContainer . layer . cornerRadius = Values . textFieldCornerRadius
publicKeyLabelContainer . layer . borderWidth = Values . borderThickness
publicKeyLabelContainer . layer . borderColor = Colors . text . cgColor
2019-12-09 00:01:10 +01:00
// S e t u p s p a c e r s
let topSpacer = UIView . vStretchingSpacer ( )
let bottomSpacer = UIView . vStretchingSpacer ( )
2019-12-06 06:42:28 +01:00
// S e t u p r e g i s t e r b u t t o n
let registerButton = Button ( style : . prominentFilled , size : . large )
registerButton . setTitle ( NSLocalizedString ( " Continue " , comment : " " ) , for : UIControl . State . normal )
registerButton . titleLabel ! . font = . boldSystemFont ( ofSize : Values . mediumFontSize )
registerButton . addTarget ( self , action : #selector ( register ) , for : UIControl . Event . touchUpInside )
2019-12-09 00:01:10 +01:00
// S e t u p b u t t o n s t a c k v i e w
let buttonStackView = UIStackView ( arrangedSubviews : [ registerButton , copyPublicKeyButton ] )
buttonStackView . axis = . vertical
2020-01-17 05:53:56 +01:00
buttonStackView . spacing = isSmallScreen ? Values . smallSpacing : Values . mediumSpacing
2019-12-09 00:01:10 +01:00
buttonStackView . alignment = . fill
// S e t u p b u t t o n s t a c k v i e w c o n t a i n e r
let buttonStackViewContainer = UIView ( )
buttonStackViewContainer . addSubview ( buttonStackView )
buttonStackView . pin ( . leading , to : . leading , of : buttonStackViewContainer , withInset : Values . massiveSpacing )
buttonStackView . pin ( . top , to : . top , of : buttonStackViewContainer )
buttonStackViewContainer . pin ( . trailing , to : . trailing , of : buttonStackView , withInset : Values . massiveSpacing )
buttonStackViewContainer . pin ( . bottom , to : . bottom , of : buttonStackView )
2019-12-06 06:42:28 +01:00
// S e t u p l e g a l l a b e l
2019-12-09 00:27:01 +01:00
legalLabel . isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer ( target : self , action : #selector ( handleLegalLabelTapped ) )
legalLabel . addGestureRecognizer ( tapGestureRecognizer )
// S e t u p l e g a l l a b e l c o n t a i n e r
let legalLabelContainer = UIView ( )
legalLabelContainer . set ( . height , to : Values . onboardingButtonBottomOffset )
legalLabelContainer . addSubview ( legalLabel )
legalLabel . pin ( . leading , to : . leading , of : legalLabelContainer , withInset : Values . massiveSpacing )
legalLabel . pin ( . top , to : . top , of : legalLabelContainer )
legalLabelContainer . pin ( . trailing , to : . trailing , of : legalLabel , withInset : Values . massiveSpacing )
2020-01-17 05:53:56 +01:00
legalLabelContainer . pin ( . bottom , to : . bottom , of : legalLabel , withInset : isSmallScreen ? 6 : 10 )
2019-12-09 00:01:10 +01:00
// S e t u p t o p s t a c k v i e w
let topStackView = UIStackView ( arrangedSubviews : [ titleLabel , explanationLabel , publicKeyLabelContainer ] )
topStackView . axis = . vertical
2020-01-17 05:53:56 +01:00
topStackView . spacing = isSmallScreen ? Values . smallSpacing : Values . veryLargeSpacing
2019-12-09 00:01:10 +01:00
topStackView . alignment = . fill
// S e t u p t o p s t a c k v i e w c o n t a i n e r
let topStackViewContainer = UIView ( )
topStackViewContainer . addSubview ( topStackView )
topStackView . pin ( . leading , to : . leading , of : topStackViewContainer , withInset : Values . veryLargeSpacing )
topStackView . pin ( . top , to : . top , of : topStackViewContainer )
topStackViewContainer . pin ( . trailing , to : . trailing , of : topStackView , withInset : Values . veryLargeSpacing )
topStackViewContainer . pin ( . bottom , to : . bottom , of : topStackView )
2019-12-06 06:42:28 +01:00
// S e t u p m a i n s t a c k v i e w
2019-12-09 00:27:01 +01:00
let mainStackView = UIStackView ( arrangedSubviews : [ topSpacer , topStackViewContainer , bottomSpacer , buttonStackViewContainer , legalLabelContainer ] )
2019-12-06 06:42:28 +01:00
mainStackView . axis = . vertical
mainStackView . alignment = . fill
view . addSubview ( mainStackView )
mainStackView . pin ( to : view )
2019-12-09 00:01:10 +01:00
topSpacer . heightAnchor . constraint ( equalTo : bottomSpacer . heightAnchor , multiplier : 1 ) . isActive = true
2019-12-06 06:42:28 +01:00
// P e f o r m i n i t i a l s e e d u p d a t e
updateSeed ( )
}
// MARK: G e n e r a l
@objc private func enableCopyButton ( ) {
copyPublicKeyButton . isUserInteractionEnabled = true
UIView . transition ( with : copyPublicKeyButton , duration : 0.25 , options : . transitionCrossDissolve , animations : {
2019-12-13 05:02:05 +01:00
self . copyPublicKeyButton . setTitle ( NSLocalizedString ( " Copy " , comment : " " ) , for : UIControl . State . normal )
2019-12-06 06:42:28 +01:00
} , completion : nil )
}
// MARK: U p d a t i n g
private func updateSeed ( ) {
seed = Randomness . generateRandomBytes ( 16 )
}
private func updateKeyPair ( ) {
keyPair = Curve25519 . generateKeyPair ( fromSeed : seed + seed )
}
private func updatePublicKeyLabel ( ) {
2020-01-08 06:10:12 +01:00
let hexEncodedPublicKey = keyPair . hexEncodedPublicKey
let characterCount = hexEncodedPublicKey . count
var count = 0
let limit = 32
func animate ( ) {
let numberOfIndexesToShuffle = 32 - count
let indexesToShuffle = ( 0. . < characterCount ) . shuffled ( ) [ 0. . < numberOfIndexesToShuffle ]
var mangledHexEncodedPublicKey = hexEncodedPublicKey
for index in indexesToShuffle {
let startIndex = mangledHexEncodedPublicKey . index ( mangledHexEncodedPublicKey . startIndex , offsetBy : index )
let endIndex = mangledHexEncodedPublicKey . index ( after : startIndex )
mangledHexEncodedPublicKey . replaceSubrange ( startIndex . . < endIndex , with : " 0123456789abcdef__ " . shuffled ( ) [ 0. . < 1 ] )
}
count += 1
if count < limit {
publicKeyLabel . text = mangledHexEncodedPublicKey
Timer . scheduledTimer ( withTimeInterval : 0.032 , repeats : false ) { _ in
animate ( )
}
} else {
publicKeyLabel . text = hexEncodedPublicKey
}
}
animate ( )
2019-12-06 06:42:28 +01:00
}
// MARK: I n t e r a c t i o n
@objc private func register ( ) {
let identityManager = OWSIdentityManager . shared ( )
let databaseConnection = identityManager . value ( forKey : " dbConnection " ) as ! YapDatabaseConnection
databaseConnection . setObject ( seed . toHexString ( ) , forKey : " LKLokiSeed " , inCollection : OWSPrimaryStorageIdentityKeyStoreCollection )
databaseConnection . setObject ( keyPair ! , forKey : OWSPrimaryStorageIdentityKeyStoreIdentityKey , inCollection : OWSPrimaryStorageIdentityKeyStoreCollection )
2019-12-09 01:30:26 +01:00
TSAccountManager . sharedInstance ( ) . phoneNumberAwaitingVerification = keyPair ! . hexEncodedPublicKey
let displayNameVC = DisplayNameVC ( )
navigationController ! . pushViewController ( displayNameVC , animated : true )
2019-12-06 06:42:28 +01:00
}
@objc private func copyPublicKey ( ) {
UIPasteboard . general . string = keyPair . hexEncodedPublicKey
copyPublicKeyButton . isUserInteractionEnabled = false
UIView . transition ( with : copyPublicKeyButton , duration : 0.25 , options : . transitionCrossDissolve , animations : {
self . copyPublicKeyButton . setTitle ( NSLocalizedString ( " Copied " , comment : " " ) , for : UIControl . State . normal )
} , completion : nil )
Timer . scheduledTimer ( timeInterval : 4 , target : self , selector : #selector ( enableCopyButton ) , userInfo : nil , repeats : false )
}
2019-12-09 00:27:01 +01:00
@objc private func handleLegalLabelTapped ( _ tapGestureRecognizer : UITapGestureRecognizer ) {
let url = URL ( string : " https://github.com/loki-project/loki-messenger-ios/blob/master/privacy-policy.md " ) !
UIApplication . shared . open ( url )
}
2019-12-06 06:42:28 +01:00
}