Skip to content

Commit

Permalink
[Feature] 로그인, 온보딩, 설정화면 QA 수정 (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
Daltonicc authored Feb 24, 2023
2 parents 3f8e189 + b079abb commit bca5cd9
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 46 deletions.
41 changes: 28 additions & 13 deletions Fitfty/Projects/Auth/Sources/Auth/AuthView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class AuthView: UIView {
private let logoImageView = UIImageView()
private let snsLabel = UILabel()
private let snsImageStackView = UIStackView()
private let acceptPrivacyLabel = UILabel()
private let acceptPrivacyTextView = LinksTextView()
private let kakaoButton = UIButton()
private let appleButton = UIButton()
private let enterWithoutLoginButton = UIButton()
Expand Down Expand Up @@ -47,11 +47,15 @@ final class AuthView: UIView {
loginProblemButton.addTarget(target, action: action, for: .touchUpInside)
}

func setAcceptPrivacyTextViewLinkAction(tapLink: @escaping (URL) -> Bool) {
acceptPrivacyTextView.onLinkTap = tapLink
}

private func configure() {
configureLogoImageView()
configureLoginProblemButton()
configureEnterButtonWithoutLogin()
configureAcceptPrivacyLabel()
configureAcceptPrivacyTextView()
configureSnsImageStackView()
configureSnsLabel()
}
Expand Down Expand Up @@ -100,23 +104,30 @@ final class AuthView: UIView {
enterWithoutLoginButton.layer.borderWidth = Style.EnterWithoutLoginButton.borderWidth
}

private func configureAcceptPrivacyLabel() {
addSubviews(acceptPrivacyLabel)
private func configureAcceptPrivacyTextView() {
addSubviews(acceptPrivacyTextView)
NSLayoutConstraint.activate([
acceptPrivacyLabel.bottomAnchor.constraint(equalTo: enterWithoutLoginButton.topAnchor,
constant: -Style.AcceptPrivacyLabel.margin),
acceptPrivacyLabel.centerXAnchor.constraint(equalTo: centerXAnchor)
acceptPrivacyTextView.bottomAnchor.constraint(equalTo: enterWithoutLoginButton.topAnchor,
constant: -Style.AcceptPrivacyTextView.margin),
acceptPrivacyTextView.centerXAnchor.constraint(equalTo: centerXAnchor)
])

let termsOfUse = Style.AcceptPrivacyTextView.termsOfUse
let privacy = Style.AcceptPrivacyTextView.privacy

acceptPrivacyTextView.font = Style.AcceptPrivacyTextView.font
acceptPrivacyTextView.textColor = Style.AcceptPrivacyTextView.textColor.color
acceptPrivacyTextView.text = "서비스 가입 시 \(termsOfUse)\(privacy)에 동의하게 돼요."
acceptPrivacyTextView.addLinks([
termsOfUse: Style.AcceptPrivacyTextView.termsOfUseLink,
privacy: Style.AcceptPrivacyTextView.privacyLink
])

acceptPrivacyLabel.text = Style.AcceptPrivacyLabel.text
acceptPrivacyLabel.font = Style.AcceptPrivacyLabel.font
acceptPrivacyLabel.textColor = Style.AcceptPrivacyLabel.textColor.color
}

private func configureSnsImageStackView() {
addSubviews(snsImageStackView)
NSLayoutConstraint.activate([
snsImageStackView.bottomAnchor.constraint(equalTo: acceptPrivacyLabel.topAnchor,
snsImageStackView.bottomAnchor.constraint(equalTo: acceptPrivacyTextView.topAnchor,
constant: -Style.SnsImageStackView.margin),
snsImageStackView.centerXAnchor.constraint(equalTo: centerXAnchor)
])
Expand Down Expand Up @@ -189,9 +200,13 @@ private extension AuthView {
static let title = "둘러보기"
}

enum AcceptPrivacyLabel {
enum AcceptPrivacyTextView {
static let margin: CGFloat = 20
static let text = "서비스 가입 시 이용약관 및 개인정보취급방침에 동의하게 돼요."
static let privacy = "개인정보이용방침"
static let privacyLink = "https://maze-mozzarella-6e5.notion.site/ed1e98c3fee5417b89f85543f4a398d2"
static let termsOfUse = "이용약관"
static let termsOfUseLink = "https://maze-mozzarella-6e5.notion.site/dd559e6017ee499fa569148b8621966d"
static let textColor = CommonAsset.Colors.gray04
static let font = FitftyFont.appleSDBold(size: 12).font
}
Expand Down
5 changes: 3 additions & 2 deletions Fitfty/Projects/Auth/Sources/Auth/AuthViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ extension AuthViewController: MFMailComposeViewControllerDelegate {
let mailViewController = MFMailComposeViewController()
mailViewController.mailComposeDelegate = self
mailViewController.setToRecipients(["[email protected]"])
mailViewController.setSubject("로그인 문제")
mailViewController.setMessageBody("로그인에 어떤 문제가 있나요?", isHTML: false)
mailViewController.setSubject("로그인 문제 문의")
mailViewController.setMessageBody("문제 내용(스크린샷 또는 녹화 화면 첨부 가능):\n사용한 기기 종류:\n문의 답변을 받을 연락처:",
isHTML: false)

return mailViewController
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ final public class AuthIntroViewController: UIViewController {

private func autoScroll() {
let contentOffsetX = collectionView.contentOffset.x
let afterContentOffsetX = contentOffsetX + 1
let afterContentOffsetX = contentOffsetX + 1.5

if afterContentOffsetX > 600 {
return
Expand Down
52 changes: 52 additions & 0 deletions Fitfty/Projects/Common/Sources/LinksTextView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// LinksTextView.swift
// Common
//
// Created by Watcha-Ethan on 2023/02/23.
// Copyright © 2023 Fitfty. All rights reserved.
//

import UIKit

public final class LinksTextView: UITextView, UITextViewDelegate {
public typealias Links = [String: String]
public typealias OnLinkTap = (URL) -> Bool

public var onLinkTap: OnLinkTap?

override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
isEditable = false
isSelectable = true
isScrollEnabled = false
delegate = self
}

required init?(coder: NSCoder) {
super.init(coder: coder)
}

public func addLinks(_ links: Links) {
guard attributedText.length > 0 else {
return
}
let mText = NSMutableAttributedString(attributedString: attributedText)

for (linkText, urlString) in links {
if linkText.count > 0 {
let linkRange = mText.mutableString.range(of: linkText)
mText.addAttribute(.link, value: urlString, range: linkRange)
mText.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: linkRange)
}
}
attributedText = mText
}

public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
return onLinkTap?(URL) ?? true
}

public func textViewDidChangeSelection(_ textView: UITextView) {
textView.selectedTextRange = nil
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// SettingWebViewController.swift
// Setting
// FitftyWebViewController.swift
// Common
//
// Created by Watcha-Ethan on 2023/02/14.
// Copyright © 2023 Fitfty. All rights reserved.
Expand All @@ -9,7 +9,7 @@
import UIKit
import WebKit

public final class SettingWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
public final class FitftyWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

private let webView = WKWebView(frame: .zero)
private let url: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class SettingCoordinator: Coordinator {

func start() {
let viewController = makeSettingViewController()
viewController.hidesBottomBarWhenPushed = true
navigationController.navigationBar.prefersLargeTitles = true
navigationController.pushViewController(viewController, animated: true)
}
Expand Down Expand Up @@ -109,12 +110,12 @@ extension SettingCoordinator: SettingCoordinatorInterface {
}

func showTermsOfUse() {
let webViewController = SettingWebViewController(url: "https://maze-mozzarella-6e5.notion.site/dd559e6017ee499fa569148b8621966d")
let webViewController = FitftyWebViewController(url: "https://maze-mozzarella-6e5.notion.site/dd559e6017ee499fa569148b8621966d")
navigationController.present(webViewController, animated: true)
}

func showPrivacyRule() {
let webViewController = SettingWebViewController(url: "https://maze-mozzarella-6e5.notion.site/ed1e98c3fee5417b89f85543f4a398d2")
let webViewController = FitftyWebViewController(url: "https://maze-mozzarella-6e5.notion.site/ed1e98c3fee5417b89f85543f4a398d2")
navigationController.present(webViewController, animated: true)
}

Expand Down
3 changes: 3 additions & 0 deletions Fitfty/Projects/Core/Sources/Error/SettingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum SettingError: Error {
case noBirthday
case noAvailableBirthday
case noAvailableNickname
case tooManyMessage
case overlappedNickname
case failWithdrawAccount
case noToken
Expand All @@ -30,6 +31,8 @@ extension SettingError: LocalizedError {
return NSLocalizedString("올바른 생년월일을 기입해주세요", comment: "Wrong Birthday")
case .noAvailableNickname:
return NSLocalizedString("1자 이상의 영문과 숫자조합으로 이루어진 닉네임을 기입해주세요", comment: "Wrond Nickname")
case .tooManyMessage:
return NSLocalizedString("30자 이하로 한 줄 소개를 적어주세요", comment: "Too Many Message")
case .overlappedNickname:
return NSLocalizedString("중복된 닉네임이에요", comment: "Overlapped Nickname")
case .failWithdrawAccount:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final public class GenderViewController: UIViewController {

public override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isHidden = false
}

public init(viewModel: GenderViewModel, coordinator: OnboardingCoordinatorInterface) {
Expand Down Expand Up @@ -73,13 +74,7 @@ final public class GenderViewController: UIViewController {
}

private func configureNavigationBar() {
let cancelButton = UIBarButtonItem(
image: CommonAsset.Images.btnArrowleft.image,
style: .plain,
target: self,
action: #selector(didTapBackButton(_:))
)
navigationItem.leftBarButtonItem = cancelButton
navigationItem.hidesBackButton = true
}

private func configureButtonTarget() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ final public class NicknameViewController: UIViewController {
}

private func configure() {
configureNavigationBar()
configureNicknameTextField()
configureNextButtonTarget()
}
Expand Down Expand Up @@ -102,6 +103,16 @@ final public class NicknameViewController: UIViewController {
.store(in: &cancellables)
}

private func configureNavigationBar() {
let cancelButton = UIBarButtonItem(
image: CommonAsset.Images.btnArrowleft.image,
style: .plain,
target: self,
action: #selector(didTapBackButton(_:))
)
navigationItem.leftBarButtonItem = cancelButton
}

private func configureNicknameTextField() {
contentView.setNicknameTextFieldDelegate(self)
}
Expand All @@ -114,6 +125,11 @@ final public class NicknameViewController: UIViewController {
private func didTapNextButton() {
viewModel.didTapNextButton()
}

@objc
private func didTapBackButton(_ sender: UITapGestureRecognizer) {
coordinator.pop()
}
}

extension NicknameViewController: UITextFieldDelegate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ extension SettingViewController: MFMailComposeViewControllerDelegate {
mailViewController.mailComposeDelegate = self
mailViewController.setToRecipients(["[email protected]"])
mailViewController.setSubject("문의하기")
mailViewController.setMessageBody("서비스 이용에 어떤 문제가 있나요?", isHTML: false)
mailViewController.setMessageBody("문제 내용(스크린샷 또는 녹화 화면 첨부 가능):\n사용한 기기 종류:\n문의 답변을 받을 연락처:", isHTML: false)

return mailViewController
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,6 @@ public final class PersonalInfoViewModel: ViewModelType {
}

func didTapSaveButton(nickname: String?, birthday: String?) {
guard let nickname = nickname else {
currentState.send(.showErrorAlert(SettingError.noNickname))
return
}

guard let birthday = birthday else {
currentState.send(.showErrorAlert(SettingError.noBirthday))
return
}

checkAvailableNickname(nickname)
checkAvailableBirthday(birthday)

Expand Down Expand Up @@ -88,6 +78,7 @@ public final class PersonalInfoViewModel: ViewModelType {
nickname: response.data?.nickname,
birtyday: response.data?.birthday,
gender: response.data?.gender)

currentState.send(.updateUserPrivacy(userPrivacy: userPrivacy))
} catch {
currentState.send(.showErrorAlert(error))
Expand Down Expand Up @@ -136,27 +127,34 @@ private extension PersonalInfoViewModel {
try await repository.updateUserPrivacy(nickname: nickname,
birthday: birthday,
gender: gender)
DefaultUserManager.shared.updateGender(Gender(rawValue: gender) ?? .female)
currentState.send(.popView)
} catch {
currentState.send(.showErrorAlert(error))
}
}
}

func checkAvailableNickname(_ nickname: String) {
self.userPrivacy.nickname = nickname
func checkAvailableNickname(_ nickname: String?) {
userPrivacy.nickname = nickname
let regex = "^[0-9a-zA-Z._]{1,30}$"
if nickname.range(of: regex, options: .regularExpression) != nil {
if nickname?.range(of: regex, options: .regularExpression) != nil {
hasAvailableNickname = true
} else {
hasAvailableNickname = false
}
}

func checkAvailableBirthday(_ birthday: String) {
self.userPrivacy.birtyday = birthday
func checkAvailableBirthday(_ birthday: String?) {
if birthday?.isEmpty == true {
userPrivacy.birtyday = nil
hasAvailableBirthday = true
return
}

userPrivacy.birtyday = birthday
let regex = "^[0-9]{6}$"
if birthday.range(of: regex, options: .regularExpression) != nil {
if birthday?.range(of: regex, options: .regularExpression) != nil {
hasAvailableBirthday = true
} else {
hasAvailableBirthday = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public final class ProfileSettingViewModel: ViewModelType {
}

func didTapSaveButton(message: String?) {
guard checkAvailableMessage(message) else {
return
}

Task {
do {
var url: String?
Expand Down Expand Up @@ -69,6 +73,7 @@ public final class ProfileSettingViewModel: ViewModelType {

extension ProfileSettingViewModel {
private func saveUserProfile(imageUrl: String?, message: String?) {
let message = message?.isEmpty == true ? nil : message
Task {
do {
try await repository.updateUserProfile(profilePictureUrl: imageUrl, message: message)
Expand All @@ -80,6 +85,14 @@ extension ProfileSettingViewModel {
}
}

private func checkAvailableMessage(_ message: String?) -> Bool {
guard message?.count ?? 0 <= 30 else {
currentState.send(.showErrorAlert(SettingError.tooManyMessage))
return false
}
return true
}

private func filenameFromFilepath(_ filepath: String?) -> String? {
guard let filepath = filepath else {
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ final public class WithdrawViewController: UIViewController {

private func autoScroll() {
let contentOffsetX = collectionView.contentOffset.x
let afterContentOffsetX = contentOffsetX + 1
let afterContentOffsetX = contentOffsetX + 1.5

if afterContentOffsetX > 350 {
return
Expand Down

0 comments on commit bca5cd9

Please sign in to comment.