2021-02-05 10:53:00 +01:00
//
// M a s t o d o n R e g i s t e r V i e w M o d e l . s w i f t
// M a s t o d o n
//
// C r e a t e d b y M a i n a s u K C i r n o o n 2 0 2 1 - 2 - 5 .
//
import Combine
2021-02-20 06:55:06 +01:00
import Foundation
2021-02-05 10:53:00 +01:00
import MastodonSDK
2021-02-20 06:55:06 +01:00
import UIKit
2021-02-05 10:53:00 +01:00
final class MastodonRegisterViewModel {
2021-02-20 10:13:16 +01:00
var disposeBag = Set < AnyCancellable > ( )
2021-02-05 10:53:00 +01:00
// i n p u t
let domain : String
2021-02-20 12:54:08 +01:00
let authenticateInfo : AuthenticationViewModel . AuthenticateInfo
2021-02-05 10:53:00 +01:00
let applicationToken : Mastodon . Entity . Token
2021-02-20 12:54:08 +01:00
2021-02-05 10:53:00 +01:00
let isRegistering = CurrentValueSubject < Bool , Never > ( false )
2021-02-20 10:13:16 +01:00
let username = CurrentValueSubject < String ? , Never > ( nil )
2021-02-20 11:24:23 +01:00
let displayname = CurrentValueSubject < String ? , Never > ( nil )
let email = CurrentValueSubject < String ? , Never > ( nil )
let password = CurrentValueSubject < String ? , Never > ( nil )
2021-02-05 10:53:00 +01:00
// o u t p u t
let applicationAuthorization : Mastodon . API . OAuth . Authorization
2021-02-20 11:24:23 +01:00
2021-02-20 10:13:16 +01:00
let isUsernameValid = CurrentValueSubject < Bool ? , Never > ( nil )
2021-02-20 11:24:23 +01:00
let isDisplaynameValid = CurrentValueSubject < Bool ? , Never > ( nil )
let isEmailValid = CurrentValueSubject < Bool ? , Never > ( nil )
let isPasswordValid = CurrentValueSubject < Bool ? , Never > ( nil )
2021-02-05 10:53:00 +01:00
let error = CurrentValueSubject < Error ? , Never > ( nil )
2021-02-20 12:54:08 +01:00
init (
domain : String ,
authenticateInfo : AuthenticationViewModel . AuthenticateInfo ,
applicationToken : Mastodon . Entity . Token
) {
2021-02-05 10:53:00 +01:00
self . domain = domain
2021-02-20 12:54:08 +01:00
self . authenticateInfo = authenticateInfo
2021-02-05 10:53:00 +01:00
self . applicationToken = applicationToken
self . applicationAuthorization = Mastodon . API . OAuth . Authorization ( accessToken : applicationToken . accessToken )
2021-02-20 10:13:16 +01:00
username
. map { username in
guard let username = username else {
return nil
}
return ! username . isEmpty
}
. assign ( to : \ . value , on : isUsernameValid )
. store ( in : & disposeBag )
2021-02-20 11:24:23 +01:00
displayname
. map { displayname in
guard let displayname = displayname else {
return nil
}
return ! displayname . isEmpty
}
. assign ( to : \ . value , on : isDisplaynameValid )
. store ( in : & disposeBag )
email
. map { [ weak self ] email in
guard let self = self else { return nil }
guard let email = email else {
return nil
}
return ! email . isEmpty && self . isValidEmail ( email )
}
. assign ( to : \ . value , on : isEmailValid )
. store ( in : & disposeBag )
password
. map { [ weak self ] password in
guard let self = self else { return nil }
guard let password = password else {
return nil
}
let result = self . validatePassword ( text : password )
return ! password . isEmpty && result . 0 && result . 1 && result . 2
}
. assign ( to : \ . value , on : isPasswordValid )
. store ( in : & disposeBag )
2021-02-05 10:53:00 +01:00
}
2021-02-20 06:55:06 +01:00
}
extension MastodonRegisterViewModel {
func isValidEmail ( _ email : String ) -> Bool {
let emailRegEx = " [A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+ \\ .[A-Za-z]{2,64} "
2021-02-20 11:24:23 +01:00
let emailPred = NSPredicate ( format : " SELF MATCHES %@ " , emailRegEx )
2021-02-20 06:55:06 +01:00
return emailPred . evaluate ( with : email )
}
2021-02-05 10:53:00 +01:00
2021-02-20 06:55:06 +01:00
func validatePassword ( text : String ) -> ( Bool , Bool , Bool ) {
let trimmedText = text . trimmingCharacters ( in : . whitespaces )
let isEightCharacters = trimmedText . count >= 8
let isOneNumber = trimmedText . range ( of : " .*[0-9] " , options : . regularExpression ) != nil
let isOneSpecialCharacter = trimmedText . trimmingCharacters ( in : . decimalDigits ) . trimmingCharacters ( in : . letters ) . count > 0
return ( isEightCharacters , isOneNumber , isOneSpecialCharacter )
}
func attributeStringForUsername ( ) -> NSAttributedString {
let resultAttributeString = NSMutableAttributedString ( )
let redImage = NSTextAttachment ( )
let font = UIFont . preferredFont ( forTextStyle : . caption1 )
let configuration = UIImage . SymbolConfiguration ( font : font )
redImage . image = UIImage ( systemName : " xmark.octagon.fill " , withConfiguration : configuration ) ? . withTintColor ( Asset . Colors . lightDangerRed . color )
let imageAttribute = NSAttributedString ( attachment : redImage )
let stringAttribute = NSAttributedString ( string : " This username is taken. " , attributes : [ NSAttributedString . Key . font : font , NSAttributedString . Key . foregroundColor : Asset . Colors . lightDangerRed . color ] )
resultAttributeString . append ( imageAttribute )
resultAttributeString . append ( stringAttribute )
return resultAttributeString
}
func attributeStringForPassword ( eightCharacters : Bool = false , oneNumber : Bool = false , oneSpecialCharacter : Bool = false ) -> NSAttributedString {
let font = UIFont . preferredFont ( forTextStyle : . caption1 )
let color = UIColor . black
let falseColor = UIColor . clear
let attributeString = NSMutableAttributedString ( )
let start = NSAttributedString ( string : " Your password needs at least: \n " , attributes : [ NSAttributedString . Key . font : font , NSAttributedString . Key . foregroundColor : color ] )
attributeString . append ( start )
2021-02-20 11:24:23 +01:00
attributeString . append ( checkmarkImage ( color : eightCharacters ? color : falseColor ) )
2021-02-20 06:55:06 +01:00
let eightCharactersDescription = NSAttributedString ( string : " Eight characters \n " , attributes : [ NSAttributedString . Key . font : font , NSAttributedString . Key . foregroundColor : color ] )
attributeString . append ( eightCharactersDescription )
2021-02-20 11:24:23 +01:00
attributeString . append ( checkmarkImage ( color : oneNumber ? color : falseColor ) )
2021-02-20 06:55:06 +01:00
let oneNumberDescription = NSAttributedString ( string : " One number \n " , attributes : [ NSAttributedString . Key . font : font , NSAttributedString . Key . foregroundColor : color ] )
attributeString . append ( oneNumberDescription )
2021-02-20 11:24:23 +01:00
attributeString . append ( checkmarkImage ( color : oneSpecialCharacter ? color : falseColor ) )
2021-02-20 06:55:06 +01:00
let oneSpecialCharacterDescription = NSAttributedString ( string : " One special character \n " , attributes : [ NSAttributedString . Key . font : font , NSAttributedString . Key . foregroundColor : color ] )
attributeString . append ( oneSpecialCharacterDescription )
return attributeString
}
2021-02-20 11:24:23 +01:00
func checkmarkImage ( color : UIColor ) -> NSAttributedString {
let checkmarkImage = NSTextAttachment ( )
2021-02-20 06:55:06 +01:00
let font = UIFont . preferredFont ( forTextStyle : . caption1 )
let configuration = UIImage . SymbolConfiguration ( font : font )
2021-02-20 11:24:23 +01:00
checkmarkImage . image = UIImage ( systemName : " checkmark.circle.fill " , withConfiguration : configuration ) ? . withTintColor ( color )
return NSAttributedString ( attachment : checkmarkImage )
2021-02-20 06:55:06 +01:00
}
2021-02-05 10:53:00 +01:00
}