Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

로그인 - 온보딩 쪽 디자인 & 기능 완성 #91

Merged
merged 32 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3f522ff
refactor #87: 로그인 뷰 디자인 변경
enebin Aug 31, 2023
54d9dae
refactor #88: 개인정보 등록 뷰 디자인 변경
enebin Aug 31, 2023
2ce9cb2
refactor #87: 루트뷰 로직 개선
enebin Sep 1, 2023
873edaf
refactor #87: 루트뷰 로직 및 푸시토큰 등록 개선
enebin Sep 2, 2023
2a62396
refactor #87: 마이페이지 APi 호출 로직 개선
enebin Sep 2, 2023
8f2488f
refactor #87: 루트뷰 애니메이션 개선
enebin Sep 2, 2023
63c0c27
refactor #87: 햅틱 개선
enebin Sep 2, 2023
05dad48
fix #88: 닉네임 로직 버그 수정
enebin Sep 2, 2023
7f4977e
refactor #87: 약관 수정
enebin Sep 2, 2023
f499971
refactor #87: 카카오 로그인 세팅
enebin Sep 2, 2023
b3b93be
refactor #87: xcconfig 세팅
enebin Sep 2, 2023
e983ace
feature #89: 마이페이지에 포토/설정 버튼 추가
enebin Sep 2, 2023
a5a6e54
feature #89: 마이페이지에 설정 네비게이션 로직 추가
enebin Sep 2, 2023
1ad62f2
feature #89: 네비게이션 바 커스텀
enebin Sep 2, 2023
3ab0e46
fix #89: 홈 뷰 애니메이션 버그 수정
enebin Sep 3, 2023
3771f8a
fix #89: 웹뷰 헤더 토큰 추가
enebin Sep 3, 2023
0706617
fix #89: 스택 오버플로우 버그 수정
enebin Sep 3, 2023
07be2dd
feature #89: 루트뷰에서 로그아웃 액션 수신
enebin Sep 4, 2023
fa42493
refactor #89: 루트뷰를 스위치스토어로 변경
enebin Sep 4, 2023
c80e875
refactor #89: 백그라운드 블러 로직 변경
enebin Sep 4, 2023
e875ec1
Merge branch 'refactor/루트뷰-통한의-리팩토링' into feature/setting-view(#89)
enebin Sep 4, 2023
9197ccf
refactor #89: 파일 이름 변경
enebin Sep 4, 2023
9563edd
refactor #89: 액션 이름 변경
enebin Sep 4, 2023
88ddca0
feature #89: 푸시알림 관리를 위한 매니저 클래스 추가
enebin Sep 4, 2023
d0ae5d6
feature #89: 푸시알림 등록 로직 수정
enebin Sep 4, 2023
c5beda8
refactor #89: 설정 진입 네비게이션 로직 개선
enebin Sep 4, 2023
f133d2b
refactor #89: 코드 개선
enebin Sep 5, 2023
ea19516
refactor #89: 웹 뷰 로딩속도 개선
enebin Sep 5, 2023
6f15114
refactor #89: 홈에서 테스트 진입 UX 개선
enebin Sep 6, 2023
ae04e23
feature #89: 권한 관련 에러처리 및 `alert` 추가
enebin Sep 6, 2023
f750031
chore #89: 코드린트
enebin Sep 6, 2023
6662b61
Merge pull request #92 from Nexters/feature/setting-view(#89)
enebin Sep 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor #88: 개인정보 등록 뷰 디자인 변경
  • Loading branch information
enebin committed Sep 3, 2023
commit 54d9daef74bd18576e61821eccaf149b12c29d45
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// TextFieldPlaceholder.swift
// Core
//
// Created by 이영빈 on 2023/08/31.
// Copyright © 2023 team.humanwave. All rights reserved.
//

import SwiftUI

public extension View {
func placeholder<Content: View>(
when shouldShow: Bool,
alignment: Alignment = .leading,
@ViewBuilder placeholder: () -> Content
) -> some View {
ZStack(alignment: alignment) {
placeholder().opacity(shouldShow ? 1 : 0)
self
}
}
}
122 changes: 79 additions & 43 deletions Projects/Features/Sources/Registration/RegistrationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Core
import DSKit
import SwiftUI
import PhotosUI

Expand All @@ -22,6 +23,7 @@ public struct RegistrationView: View {
}

// 닉네임 관련 프로퍼티
@FocusState private var isTextFieldFocused: Bool
@State private var nickname = "" // 사용자가 새롭게 입력한 닉네임
@State private var beforeNickname = "" // 기존에 입력했던 닉네임
@State private var isShake = false // 최대 글자 수를 넘긴 경우 좌, 우로 떨리는 애니메이션
Expand All @@ -32,7 +34,12 @@ public struct RegistrationView: View {

public var body: some View {
WithViewStore(store, observe: { $0 }) { viewStore in
VStack(spacing: 12) {
VStack(spacing: 0) {
Text.keyme("회원가입", font: .body3Semibold)
.foregroundColor(.white)
.padding(.top, 16)
.padding(.bottom, 24)

// 프로필 이미지를 등록하는 Circle
PhotosPicker(selection: $selectedImage, matching: .images, photoLibrary: .shared()) {
profileImage(imageData: selectedImageData)
Expand All @@ -49,57 +56,68 @@ public struct RegistrationView: View {
}
}

// 닉네임 관련 안내메세지
Spacer().frame(height: 59)

HStack(alignment: .center, spacing: 4) {
Text("닉네임")
.font(.system(size: 14))
Text.keyme("닉네임", font: .body3Regular)
.foregroundColor(.white)

Text("(\(nickname.count)/6)")
.font(.system(size: 12))
.foregroundColor(.gray)
Text.keyme("(\(nickname.count)/6)", font: .caption1)
.foregroundColor(DSKitAsset.Color.keymeMediumgray.swiftUIColor)

Spacer()

Text("2~6자리 한글, 영어, 숫자")
.font(.system(size: 12))
Text.keyme("2~6자리 한글, 영어, 숫자", font: .caption1)
.foregroundColor(.white)
}
.padding(.horizontal, 2)

Spacer().frame(height: 12)

// 닉네임을 입력하는 TextField
TextField("닉네임을 입력해주세요.", text: $nickname)
.font(.system(size: 16))
TextField("Nickname", text: $nickname)
.focused($isTextFieldFocused)
.placeholder(when: nickname.isEmpty, placeholder: {
Text.keyme("닉네임을 입력해주세요.", font: .body3Regular)
.foregroundColor(.white.opacity(0.4))
})
.foregroundColor(.white)
.padding(.horizontal, 10)
.frame(height: 50)
.padding(.horizontal)
.overlay(
RoundedRectangle(cornerRadius: 4)
.stroke(.gray, lineWidth: 1)
.stroke(.white.opacity(0.3), lineWidth: 1)
)
.background(.black.opacity(0.4))
.modifier(Shake(isShake: $isShake))

if !nickname.isEmpty, let isValid = viewStore.isNicknameAvailable {
if
!nickname.isEmpty,
let isValid = viewStore.state.isNicknameAvailable
{
ValidateNicknameView(isValid: isValid)
.padding(.top, 12)
}

Spacer(minLength: 50)

// 닉네임 관련 안내메세지
Rectangle()
.frame(height: 80)
.foregroundColor(.gray)
.foregroundColor(
DSKitAsset.Color.keymeBlack.swiftUIColor.opacity(0.8))
.cornerRadius(8)
.overlay(
Text("친구들이 원할하게 문제를 풀 수 있도록, 나를 가장 잘 나타내는 닉네임으로 설정해주세요. \(viewStore.canRegister.description)")
.font(.system(size: 14))
.fontWeight(.semibold)
Text.keyme("친구들이 원활하게 문제를 풀 수 있도록, 나를 가장 잘 나타내는 닉네임으로 설정해주세요.", font: .body4)
.lineSpacing(10)
.foregroundColor(.white)
.padding(.horizontal, 8)
)

Spacer()

.padding(.vertical, 24)

// 다음 페이지로 넘어가기 위한 Button
Button(action: {
viewStore.send(
.finishRegister(
nickname: viewStore.state.nicknameTextFieldString,
nickname: viewStore.nicknameTextFieldString,
thumbnailURL: viewStore.thumbnailURL,
originalImageURL: viewStore.originalImageURL))
}) {
Expand All @@ -115,11 +133,14 @@ public struct RegistrationView: View {
}
}
.foregroundColor(.white)
.background(viewStore.canRegister ? .black : .gray)
.background(viewStore.state.canRegister ? .black : .white.opacity(0.3))
.cornerRadius(16)
.disabled(viewStore.canRegister ? false : true)
.padding(.bottom, 20)
.disabled(viewStore.state.canRegister ? false : true)
}
.onTapGesture {
isTextFieldFocused = false
}
.modifier(DismissKeyboardOnTap())
.padding(.horizontal, 16)
.onChange(of: nickname) { newValue in
guard 1 <= newValue.count, newValue.count <= 6 else {
Expand All @@ -136,14 +157,24 @@ public struct RegistrationView: View {

viewStore.send(.debouncedNicknameUpdate(text: newValue))
}
.fullFrame()
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
}

// 닉네임에 대한 검증 여부를 보여주는 뷰
extension RegistrationView {
func profileImage(imageData: Data?) -> some View {
ZStack(alignment: .bottomTrailing) {
let outercircleSize = 160.0
let iconSize = 33.3

return ZStack(alignment: .center) {
Circle()
.foregroundColor(.white.opacity(0.15))
.overlay(Circle().stroke(.white.opacity(0.30), lineWidth: 1))
.frame(width: outercircleSize, height: outercircleSize)

Group {
if
let selectedImageData = imageData,
Expand All @@ -152,25 +183,22 @@ extension RegistrationView {
Image(uiImage: profileImage)
.resizable()
.scaledToFill()
.frame(width: outercircleSize - 20, height: outercircleSize - 20)
} else {
Circle()
.foregroundColor(.gray)
.overlay(Circle().stroke(.white, lineWidth: 1))
ZStack {
Circle()
.foregroundColor(.black.opacity(0.8))
.frame(width: outercircleSize - 20, height: outercircleSize - 20)

Image(systemName: "photo")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconSize, height: iconSize)
.foregroundColor(.white)
}
}
}
.frame(width: 160, height: 160)
.clipShape(Circle())

ZStack {
Circle()
.foregroundColor(.black)
.frame(width: 50, height: 50)
Image(systemName: "photo")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 33.3, height: 33.3)
.foregroundColor(.white)
}
}
}

Expand All @@ -192,3 +220,11 @@ extension RegistrationView {
}
}
}

struct RegistrationView_preview: PreviewProvider {
static var previews: some View {
RegistrationView(store: Store(initialState: RegistrationFeature.State(), reducer: {
RegistrationFeature()
}))
}
}
2 changes: 1 addition & 1 deletion Projects/Features/Sources/Root/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public struct RootView: View {
let loginStore = store.scope(
state: \.$logInStatus,
action: RootFeature.Action.login)

IfLetStore(loginStore) { store in
SignInView(store: store)
}
Expand Down