Merge pull request #25 from tootsuite/feature/invite
feat: add support for inviteEnabled instance
This commit is contained in:
commit
56b010a47d
|
@ -1,95 +0,0 @@
|
||||||
{
|
|
||||||
"common": {
|
|
||||||
"alerts": {},
|
|
||||||
"controls": {
|
|
||||||
"actions": {
|
|
||||||
"add": "Add",
|
|
||||||
"remove": "Remove",
|
|
||||||
"edit": "Edit",
|
|
||||||
"save": "Save",
|
|
||||||
"ok": "OK",
|
|
||||||
"confirm": "Confirm",
|
|
||||||
"continue": "Continue",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"take_photo": "Take photo",
|
|
||||||
"save_photo": "Save photo",
|
|
||||||
"sign_in": "Sign in",
|
|
||||||
"sign_up": "Sign up",
|
|
||||||
"see_more": "See More",
|
|
||||||
"preview": "Preview",
|
|
||||||
"open_in_safari": "Open in Safari"
|
|
||||||
},
|
|
||||||
"status": {
|
|
||||||
"user_boosted": "%s boosted",
|
|
||||||
"content_warning": "content warning",
|
|
||||||
"show_post": "Show Post"
|
|
||||||
},
|
|
||||||
"timeline": {
|
|
||||||
"load_more": "Load More"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"countable": {
|
|
||||||
"photo": {
|
|
||||||
"single": "photo",
|
|
||||||
"multiple": "photos"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scene": {
|
|
||||||
"welcome": {
|
|
||||||
"slogan": "Social networking\nback in your hands."
|
|
||||||
},
|
|
||||||
"server_picker": {
|
|
||||||
"title": "Pick a Server,\nany server.",
|
|
||||||
"Button": {
|
|
||||||
"Category": {
|
|
||||||
"All": "All"
|
|
||||||
},
|
|
||||||
"SeeLess": "See Less",
|
|
||||||
"SeeMore": "See More"
|
|
||||||
},
|
|
||||||
"Label": {
|
|
||||||
"Language": "LANGUAGE",
|
|
||||||
"Users": "USERS",
|
|
||||||
"Category": "CATEGORY"
|
|
||||||
},
|
|
||||||
"input": {
|
|
||||||
"placeholder": "Find a server or join your own..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"register": {
|
|
||||||
"title": "Tell us about you.",
|
|
||||||
"input": {
|
|
||||||
"username": {
|
|
||||||
"placeholder": "username",
|
|
||||||
"duplicate_prompt": "This username is taken."
|
|
||||||
},
|
|
||||||
"display_name": {
|
|
||||||
"placeholder": "display name"
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"placeholder": "email"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"placeholder": "password",
|
|
||||||
"prompt": "Your password needs at least:",
|
|
||||||
"prompt_eight_characters": "Eight characters"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"server_rules": {
|
|
||||||
"title": "Some ground rules.",
|
|
||||||
"subtitle": "These rules are set by the admins of %s.",
|
|
||||||
"prompt": "By continuing, you're subject to the terms of service and privacy policy for %s.",
|
|
||||||
"button": {
|
|
||||||
"confirm": "I Agree"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"home_timeline": {
|
|
||||||
"title": "Home"
|
|
||||||
},
|
|
||||||
"public_timeline": {
|
|
||||||
"title": "Public"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
"Common.Controls.Actions.Add" = "Add";
|
|
||||||
"Common.Controls.Actions.Cancel" = "Cancel";
|
|
||||||
"Common.Controls.Actions.Confirm" = "Confirm";
|
|
||||||
"Common.Controls.Actions.Continue" = "Continue";
|
|
||||||
"Common.Controls.Actions.Edit" = "Edit";
|
|
||||||
"Common.Controls.Actions.Ok" = "OK";
|
|
||||||
"Common.Controls.Actions.OpenInSafari" = "Open in Safari";
|
|
||||||
"Common.Controls.Actions.Preview" = "Preview";
|
|
||||||
"Common.Controls.Actions.Remove" = "Remove";
|
|
||||||
"Common.Controls.Actions.Save" = "Save";
|
|
||||||
"Common.Controls.Actions.SavePhoto" = "Save photo";
|
|
||||||
"Common.Controls.Actions.SeeMore" = "See More";
|
|
||||||
"Common.Controls.Actions.SignIn" = "Sign in";
|
|
||||||
"Common.Controls.Actions.SignUp" = "Sign up";
|
|
||||||
"Common.Controls.Actions.TakePhoto" = "Take photo";
|
|
||||||
"Common.Controls.Status.ContentWarning" = "content warning";
|
|
||||||
"Common.Controls.Status.ShowPost" = "Show Post";
|
|
||||||
"Common.Controls.Status.UserBoosted" = "%@ boosted";
|
|
||||||
"Common.Controls.Timeline.LoadMore" = "Load More";
|
|
||||||
"Common.Countable.Photo.Multiple" = "photos";
|
|
||||||
"Common.Countable.Photo.Single" = "photo";
|
|
||||||
"Scene.HomeTimeline.Title" = "Home";
|
|
||||||
"Scene.PublicTimeline.Title" = "Public";
|
|
||||||
"Scene.Register.Input.DisplayName.Placeholder" = "display name";
|
|
||||||
"Scene.Register.Input.Email.Placeholder" = "email";
|
|
||||||
"Scene.Register.Input.Password.Placeholder" = "password";
|
|
||||||
"Scene.Register.Input.Password.Prompt" = "Your password needs at least:";
|
|
||||||
"Scene.Register.Input.Password.PromptEightCharacters" = "Eight characters";
|
|
||||||
"Scene.Register.Input.Username.DuplicatePrompt" = "This username is taken.";
|
|
||||||
"Scene.Register.Input.Username.Placeholder" = "username";
|
|
||||||
"Scene.Register.Title" = "Tell us about you.";
|
|
||||||
"Scene.ServerPicker.Button.Category.All" = "All";
|
|
||||||
"Scene.ServerPicker.Button.Seeless" = "See Less";
|
|
||||||
"Scene.ServerPicker.Button.Seemore" = "See More";
|
|
||||||
"Scene.ServerPicker.Input.Placeholder" = "Find a server or join your own...";
|
|
||||||
"Scene.ServerPicker.Label.Category" = "CATEGORY";
|
|
||||||
"Scene.ServerPicker.Label.Language" = "LANGUAGE";
|
|
||||||
"Scene.ServerPicker.Label.Users" = "USERS";
|
|
||||||
"Scene.ServerPicker.Title" = "Pick a Server,
|
|
||||||
any server.";
|
|
||||||
"Scene.ServerRules.Button.Confirm" = "I Agree";
|
|
||||||
"Scene.ServerRules.Prompt" = "By continuing, you're subject to the terms of service and privacy policy for %@.";
|
|
||||||
"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@.";
|
|
||||||
"Scene.ServerRules.Title" = "Some ground rules.";
|
|
||||||
"Scene.Welcome.Slogan" = "Social networking
|
|
||||||
back in your hands.";
|
|
|
@ -84,6 +84,9 @@
|
||||||
"placeholder": "password",
|
"placeholder": "password",
|
||||||
"prompt": "Your password needs at least:",
|
"prompt": "Your password needs at least:",
|
||||||
"prompt_eight_characters": "Eight characters"
|
"prompt_eight_characters": "Eight characters"
|
||||||
|
},
|
||||||
|
"invite": {
|
||||||
|
"registration_user_invite_request": "Why do you want to join?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"success": "Success",
|
"success": "Success",
|
||||||
|
|
|
@ -141,6 +141,10 @@ internal enum L10n {
|
||||||
/// email
|
/// email
|
||||||
internal static let placeholder = L10n.tr("Localizable", "Scene.Register.Input.Email.Placeholder")
|
internal static let placeholder = L10n.tr("Localizable", "Scene.Register.Input.Email.Placeholder")
|
||||||
}
|
}
|
||||||
|
internal enum Invite {
|
||||||
|
/// Why do you want to join?
|
||||||
|
internal static let registrationUserInviteRequest = L10n.tr("Localizable", "Scene.Register.Input.Invite.RegistrationUserInviteRequest")
|
||||||
|
}
|
||||||
internal enum Password {
|
internal enum Password {
|
||||||
/// password
|
/// password
|
||||||
internal static let placeholder = L10n.tr("Localizable", "Scene.Register.Input.Password.Placeholder")
|
internal static let placeholder = L10n.tr("Localizable", "Scene.Register.Input.Password.Placeholder")
|
||||||
|
|
|
@ -40,6 +40,7 @@ tap the link to confirm your account.";
|
||||||
"Scene.Register.CheckEmail" = "Regsiter request sent. Please check your email.";
|
"Scene.Register.CheckEmail" = "Regsiter request sent. Please check your email.";
|
||||||
"Scene.Register.Input.DisplayName.Placeholder" = "display name";
|
"Scene.Register.Input.DisplayName.Placeholder" = "display name";
|
||||||
"Scene.Register.Input.Email.Placeholder" = "email";
|
"Scene.Register.Input.Email.Placeholder" = "email";
|
||||||
|
"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Why do you want to join?";
|
||||||
"Scene.Register.Input.Password.Placeholder" = "password";
|
"Scene.Register.Input.Password.Placeholder" = "password";
|
||||||
"Scene.Register.Input.Password.Prompt" = "Your password needs at least:";
|
"Scene.Register.Input.Password.Prompt" = "Your password needs at least:";
|
||||||
"Scene.Register.Input.Password.PromptEightCharacters" = "Eight characters";
|
"Scene.Register.Input.Password.PromptEightCharacters" = "Eight characters";
|
||||||
|
@ -61,4 +62,4 @@ any server.";
|
||||||
"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@.";
|
"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@.";
|
||||||
"Scene.ServerRules.Title" = "Some ground rules.";
|
"Scene.ServerRules.Title" = "Some ground rules.";
|
||||||
"Scene.Welcome.Slogan" = "Social networking
|
"Scene.Welcome.Slogan" = "Social networking
|
||||||
back in your hands.";
|
back in your hands.";
|
|
@ -97,7 +97,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O
|
||||||
textField.autocapitalizationType = .none
|
textField.autocapitalizationType = .none
|
||||||
textField.autocorrectionType = .no
|
textField.autocorrectionType = .no
|
||||||
textField.backgroundColor = .white
|
textField.backgroundColor = .white
|
||||||
textField.textColor = .black
|
textField.textColor = Asset.Colors.Label.secondary.color
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Username.placeholder,
|
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Username.placeholder,
|
||||||
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
||||||
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
||||||
|
@ -118,7 +118,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O
|
||||||
textField.autocapitalizationType = .none
|
textField.autocapitalizationType = .none
|
||||||
textField.autocorrectionType = .no
|
textField.autocorrectionType = .no
|
||||||
textField.backgroundColor = .white
|
textField.backgroundColor = .white
|
||||||
textField.textColor = .black
|
textField.textColor = Asset.Colors.Label.secondary.color
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.DisplayName.placeholder,
|
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.DisplayName.placeholder,
|
||||||
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
||||||
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
||||||
|
@ -135,7 +135,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O
|
||||||
textField.autocorrectionType = .no
|
textField.autocorrectionType = .no
|
||||||
textField.keyboardType = .emailAddress
|
textField.keyboardType = .emailAddress
|
||||||
textField.backgroundColor = .white
|
textField.backgroundColor = .white
|
||||||
textField.textColor = .black
|
textField.textColor = Asset.Colors.Label.secondary.color
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Email.placeholder,
|
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Email.placeholder,
|
||||||
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
||||||
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
||||||
|
@ -159,7 +159,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O
|
||||||
textField.keyboardType = .asciiCapable
|
textField.keyboardType = .asciiCapable
|
||||||
textField.isSecureTextEntry = true
|
textField.isSecureTextEntry = true
|
||||||
textField.backgroundColor = .white
|
textField.backgroundColor = .white
|
||||||
textField.textColor = .black
|
textField.textColor = Asset.Colors.Label.secondary.color
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Password.placeholder,
|
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Password.placeholder,
|
||||||
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
||||||
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
||||||
|
@ -170,6 +170,22 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O
|
||||||
return textField
|
return textField
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
lazy var inviteTextField: UITextField = {
|
||||||
|
let textField = UITextField()
|
||||||
|
textField.autocapitalizationType = .none
|
||||||
|
textField.autocorrectionType = .no
|
||||||
|
textField.backgroundColor = .white
|
||||||
|
textField.textColor = Asset.Colors.Label.secondary.color
|
||||||
|
textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Invite.registrationUserInviteRequest,
|
||||||
|
attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.lightSecondaryText.color,
|
||||||
|
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .headline)])
|
||||||
|
textField.borderStyle = UITextField.BorderStyle.roundedRect
|
||||||
|
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height))
|
||||||
|
textField.leftView = paddingView
|
||||||
|
textField.leftViewMode = .always
|
||||||
|
return textField
|
||||||
|
}()
|
||||||
|
|
||||||
let signUpButton: UIButton = {
|
let signUpButton: UIButton = {
|
||||||
let button = UIButton(type: .system)
|
let button = UIButton(type: .system)
|
||||||
button.titleLabel?.font = .preferredFont(forTextStyle: .headline)
|
button.titleLabel?.font = .preferredFont(forTextStyle: .headline)
|
||||||
|
@ -226,7 +242,9 @@ extension MastodonRegisterViewController {
|
||||||
stackView.addArrangedSubview(emailTextField)
|
stackView.addArrangedSubview(emailTextField)
|
||||||
stackView.addArrangedSubview(passwordTextField)
|
stackView.addArrangedSubview(passwordTextField)
|
||||||
stackView.addArrangedSubview(passwordCheckLabel)
|
stackView.addArrangedSubview(passwordCheckLabel)
|
||||||
|
if self.viewModel.approvalRequired {
|
||||||
|
stackView.addArrangedSubview(inviteTextField)
|
||||||
|
}
|
||||||
// scrollView
|
// scrollView
|
||||||
view.addSubview(scrollView)
|
view.addSubview(scrollView)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
@ -445,6 +463,31 @@ extension MastodonRegisterViewController {
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
if self.viewModel.approvalRequired {
|
||||||
|
|
||||||
|
inviteTextField.delegate = self
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
inviteTextField.heightAnchor.constraint(equalToConstant: 50).priority(.defaultHigh)
|
||||||
|
])
|
||||||
|
|
||||||
|
viewModel.inviteValidateState
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] validateState in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.setTextFieldValidAppearance(self.inviteTextField, validateState: validateState)
|
||||||
|
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
NotificationCenter.default
|
||||||
|
.publisher(for: UITextField.textDidChangeNotification, object: inviteTextField)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.viewModel.invite.value = self.inviteTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
signUpButton.addTarget(self, action: #selector(MastodonRegisterViewController.signUpButtonPressed(_:)), for: .touchUpInside)
|
signUpButton.addTarget(self, action: #selector(MastodonRegisterViewController.signUpButtonPressed(_:)), for: .touchUpInside)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,25 +499,6 @@ extension MastodonRegisterViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonRegisterViewController: UITextFieldDelegate {
|
extension MastodonRegisterViewController: UITextFieldDelegate {
|
||||||
|
|
||||||
// FIXME: keyboard listener trigger when switch between text fields. Maybe could remove it
|
|
||||||
// func textFieldDidBeginEditing(_ textField: UITextField) {
|
|
||||||
// // align to password label when overlap
|
|
||||||
// if textField === passwordTextField,
|
|
||||||
// KeyboardResponderService.shared.isShow.value,
|
|
||||||
// KeyboardResponderService.shared.state.value == .dock
|
|
||||||
// {
|
|
||||||
// let endFrame = KeyboardResponderService.shared.willEndFrame.value
|
|
||||||
// let contentFrame = scrollView.convert(signUpButton.frame, to: nil)
|
|
||||||
// let padding = contentFrame.maxY - endFrame.minY
|
|
||||||
// if padding > 0 {
|
|
||||||
// let contentOffsetY = scrollView.contentOffset.y
|
|
||||||
// DispatchQueue.main.async {
|
|
||||||
// self.scrollView.setContentOffset(CGPoint(x: 0, y: contentOffsetY + padding + 16.0), animated: true)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
func textFieldDidBeginEditing(_ textField: UITextField) {
|
func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||||
let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||||
|
@ -488,6 +512,8 @@ extension MastodonRegisterViewController: UITextFieldDelegate {
|
||||||
viewModel.email.value = text
|
viewModel.email.value = text
|
||||||
case passwordTextField:
|
case passwordTextField:
|
||||||
viewModel.password.value = text
|
viewModel.password.value = text
|
||||||
|
case inviteTextField:
|
||||||
|
viewModel.invite.value = text
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -542,7 +568,7 @@ extension MastodonRegisterViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = Mastodon.API.Account.RegisterQuery(
|
let query = Mastodon.API.Account.RegisterQuery(
|
||||||
reason: nil,
|
reason: viewModel.invite.value,
|
||||||
username: username,
|
username: username,
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
|
|
|
@ -11,7 +11,6 @@ import MastodonSDK
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
final class MastodonRegisterViewModel {
|
final class MastodonRegisterViewModel {
|
||||||
|
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
// input
|
// input
|
||||||
|
@ -24,20 +23,30 @@ final class MastodonRegisterViewModel {
|
||||||
let displayName = CurrentValueSubject<String, Never>("")
|
let displayName = CurrentValueSubject<String, Never>("")
|
||||||
let email = CurrentValueSubject<String, Never>("")
|
let email = CurrentValueSubject<String, Never>("")
|
||||||
let password = CurrentValueSubject<String, Never>("")
|
let password = CurrentValueSubject<String, Never>("")
|
||||||
|
let invite = CurrentValueSubject<String, Never>("")
|
||||||
|
|
||||||
let isUsernameValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
let isUsernameValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
||||||
let isDisplayNameValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
let isDisplayNameValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
||||||
let isEmailValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
let isEmailValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
||||||
let isPasswordValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
let isPasswordValidateDalay = CurrentValueSubject<Bool, Never>(true)
|
||||||
|
let isInviteValidateDelay = CurrentValueSubject<Bool, Never>(true)
|
||||||
let isRegistering = CurrentValueSubject<Bool, Never>(false)
|
let isRegistering = CurrentValueSubject<Bool, Never>(false)
|
||||||
|
|
||||||
|
|
||||||
// output
|
// output
|
||||||
|
lazy var approvalRequired: Bool = {
|
||||||
|
if let approvalRequired = instance.approvalRequired {
|
||||||
|
return approvalRequired
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}()
|
||||||
|
|
||||||
let applicationAuthorization: Mastodon.API.OAuth.Authorization
|
let applicationAuthorization: Mastodon.API.OAuth.Authorization
|
||||||
|
|
||||||
let usernameValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
let usernameValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
||||||
let displayNameValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
let displayNameValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
||||||
let emailValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
let emailValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
||||||
let passwordValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
let passwordValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
||||||
|
let inviteValidateState = CurrentValueSubject<ValidateState, Never>(.empty)
|
||||||
|
|
||||||
let isAllValid = CurrentValueSubject<Bool, Never>(false)
|
let isAllValid = CurrentValueSubject<Bool, Never>(false)
|
||||||
|
|
||||||
|
@ -67,7 +76,7 @@ final class MastodonRegisterViewModel {
|
||||||
// 0-9 (isASCII && isNumber)
|
// 0-9 (isASCII && isNumber)
|
||||||
// _ ("_")
|
// _ ("_")
|
||||||
for char in username {
|
for char in username {
|
||||||
guard char.isASCII, (char.isLetter || char.isNumber || char == "_") else {
|
guard char.isASCII, char.isLetter || char.isNumber || char == "_" else {
|
||||||
isValid = false
|
isValid = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -97,18 +106,34 @@ final class MastodonRegisterViewModel {
|
||||||
}
|
}
|
||||||
.assign(to: \.value, on: passwordValidateState)
|
.assign(to: \.value, on: passwordValidateState)
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
if approvalRequired {
|
||||||
Publishers.CombineLatest4(
|
invite
|
||||||
|
.map { invite in
|
||||||
|
guard !invite.isEmpty else { return .empty }
|
||||||
|
return .valid
|
||||||
|
}
|
||||||
|
.assign(to: \.value, on: inviteValidateState)
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
let publisherOne = Publishers.CombineLatest4(
|
||||||
usernameValidateState.eraseToAnyPublisher(),
|
usernameValidateState.eraseToAnyPublisher(),
|
||||||
displayNameValidateState.eraseToAnyPublisher(),
|
displayNameValidateState.eraseToAnyPublisher(),
|
||||||
emailValidateState.eraseToAnyPublisher(),
|
emailValidateState.eraseToAnyPublisher(),
|
||||||
passwordValidateState.eraseToAnyPublisher()
|
passwordValidateState.eraseToAnyPublisher()
|
||||||
|
).map {
|
||||||
|
$0.0 == .valid && $0.1 == .valid && $0.2 == .valid && $0.3 == .valid
|
||||||
|
}
|
||||||
|
|
||||||
|
Publishers.CombineLatest(
|
||||||
|
publisherOne,
|
||||||
|
approvalRequired ? inviteValidateState.map {$0 == .valid}.eraseToAnyPublisher() : Just(true).eraseToAnyPublisher()
|
||||||
)
|
)
|
||||||
.map { $0.0 == .valid && $0.1 == .valid && $0.2 == .valid && $0.3 == .valid }
|
.map {
|
||||||
|
return $0 && $1
|
||||||
|
}
|
||||||
.assign(to: \.value, on: isAllValid)
|
.assign(to: \.value, on: isAllValid)
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonRegisterViewModel {
|
extension MastodonRegisterViewModel {
|
||||||
|
|
|
@ -45,7 +45,7 @@ extension Mastodon.Entity {
|
||||||
case languages
|
case languages
|
||||||
case registrations
|
case registrations
|
||||||
case approvalRequired = "approval_required"
|
case approvalRequired = "approval_required"
|
||||||
case invitesEnabled
|
case invitesEnabled = "invites_enabled"
|
||||||
case urls
|
case urls
|
||||||
case statistics
|
case statistics
|
||||||
|
|
||||||
|
|
|
@ -23,4 +23,4 @@ fi
|
||||||
|
|
||||||
#task4 clean temp file
|
#task4 clean temp file
|
||||||
rm -rf ${SRCROOT}/Localization/StringsConvertor/output
|
rm -rf ${SRCROOT}/Localization/StringsConvertor/output
|
||||||
rm -rf ${SRCROOT}/Localization/StringsConvertor/intput
|
rm -rf ${SRCROOT}/Localization/StringsConvertor/input
|
||||||
|
|
Loading…
Reference in New Issue