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

[#84] SettingView 내 ListView 분리 및 추가 리팩터링 #89

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion Soomsil-USaint/Application/AppReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct AppReducer {
case .login(.loginResponse(.success(let (info, report)))):
state = .loggedIn(HomeReducer.State(studentInfo: info, totalReportCard: report))
return .none
case .home(.path(.element(id: _, action: .setting(.alert(.presented(.logout)))))):
case .home(.path(.element(id: _, action: .setting(.alert(.presented(.confirmLogoutTapped)))))):
state = .loggedOut(LoginReducer.State())
return .none
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ struct SettingReducer {
struct State {
@Shared(.appStorage("permission")) var permission = false
@Presents var alert: AlertState<Action.Alert>?
// var path = StackState<Path.State>()
// var appState: AppReducer.State?
}

enum Action: BindableAction {
Expand All @@ -28,13 +26,11 @@ struct SettingReducer {
case requestPushAuthorizationResponse(Result<Bool, Error>)
case termsOfServiceButtonTapped
case privacyPolicyButtonTapped
// case path(StackActionOf<Path>)
case alert(PresentationAction<Alert>)
// case appState(AppReducer.Action)

enum Alert: Equatable {
case logout
case configurePushAuthorization
case confirmLogoutTapped
case configurePushAuthorizationTapped
}
}

Expand All @@ -50,7 +46,7 @@ struct SettingReducer {
} actions: {
ButtonState(
role: .destructive,
action: .logout) {
action: .confirmLogoutTapped) {
TextState("로그아웃")
}
ButtonState(
Expand All @@ -59,8 +55,8 @@ struct SettingReducer {
}
}
return .none
case .alert(.presented(.logout)):
// YDSToast("로그아웃", haptic: .success)
case .alert(.presented(.confirmLogoutTapped)):
YDSToast("로그아웃 완료", haptic: .success)
return .none
case .togglePushAuthorization(true):
return .run { send in
Expand All @@ -70,6 +66,7 @@ struct SettingReducer {
}
case .togglePushAuthorization(false):
state.$permission.withLock { $0 = false }
YDSToast("알림권한 거부", haptic: .success)
return .none
case .pushAuthorizationResponse(.success(let granted)):
state.$permission.withLock { $0 = granted }
Expand All @@ -79,7 +76,7 @@ struct SettingReducer {
} actions: {
ButtonState(
role: .destructive,
action: .configurePushAuthorization
action: .configurePushAuthorizationTapped
) {
TextState("설정")
}
Expand All @@ -90,6 +87,8 @@ struct SettingReducer {
} message: {
TextState("알림에 대한 권한 사용을 거부하였습니다. 기능 사용을 원하실 경우 설정 > 앱 > 숨쉴때 유세인트 > 알림 권한 허용을 해주세요.")
}
} else {
YDSToast("알림권한 허용", haptic: .success)
}
return .none
case .requestPushAuthorizationResponse(.success(let granted)):
Expand All @@ -103,37 +102,17 @@ struct SettingReducer {
}
}
return .none
case .alert(.presented(.configurePushAuthorization)):
case .alert(.presented(.configurePushAuthorizationTapped)):
debugPrint("alert permission")
return .run { send in
await send(.requestPushAuthorizationResponse(Result {
try await localNotificationClient.requestPushAuthorization()
}))
}
// case .termsOfServiceButtonTapped:
// state.path.append(
// .navigateToTermsWebView(WebReducer.State(
// url: URL(string: "https://auth.yourssu.com/terms/service.html")!)))
// return .none
// case .privacyPolicyButtonTapped:
// state.path.append(.navigateToTermsWebView(WebReducer.State(
// url: URL(string: "https://auth.yourssu.com/terms/information.html")!)))
// return .none
default:
return .none
}
}
// .ifLet(\.appState, action: \.appState) {
// AppReducer()
// }
.ifLet(\.$alert, action: \.alert)
// .forEach(\.path, action: \.path)
}
}

//extension SettingReducer {
// @Reducer
// enum Path {
// case navigateToTermsWebView(WebReducer)
// }
//}
92 changes: 92 additions & 0 deletions Soomsil-USaint/Application/Feature/Setting/View/ListRowView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// ListRowView.swift
// Soomsil-USaint
//
// Created by 최지우 on 2/5/25.
//

import SwiftUI

import YDS_SwiftUI

enum RightItem {
case none
case toggle(isPushAuthorizationEnabled: Binding<Bool>)
}

struct ListRowView: View {
let title: String
let items: [ItemModel]

init(title: String, items: [ItemModel]) {
self.title = title
self.items = items
}

var body: some View {
VStack(alignment: .leading, spacing: 0) {
Text(title)
.font(YDSFont.subtitle3)
.foregroundColor(YDSColor.textSecondary)
.padding(20)
.frame(height: 48)

Divider()
.frame(height: 0.34)
.background(YDSColor.borderThin)

ForEach(items.indices, id: \.self) { index in
HStack {
items[index]
}
}
}
}
}

struct ItemModel: View {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 가지 걸리는 건 ItemModel이란 네이밍이 적절할까 고민이긴 한데,, ItemModel하면 뭔가 View가 아닌 느낌이 더 들어서, Row나 RowView와 같은 이름이 더 적절할 것 같아요!

let text: String
let rightItem: RightItem
let action: () -> Void
@State private var isPressed: Bool = false

var body: some View {
HStack {
Text(text)
.font(YDSFont.button3)
.foregroundColor(YDSColor.textSecondary)
.padding(20)
.frame(height: 48)
.frame(maxWidth: .infinity, alignment: .leading)
.background(isPressed ? Color(red: 0.95, green: 0.96, blue: 0.97) : Color.white)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in isPressed = true }
.onEnded { _ in
isPressed = false
switch rightItem {
case .none:
action()
case .toggle(_):
break
}
}
)

switch rightItem {
case .none:
EmptyView()
case .toggle(let isPushAuthorizationEnabled):
Toggle("", isOn: isPushAuthorizationEnabled)
.labelsHidden()
.padding(.horizontal, 20)
.padding(.vertical, 20)
.tint(YDSColor.buttonPoint)
.frame(height: 48)
.onChange(of: isPushAuthorizationEnabled.wrappedValue) { newValue in
action()
}
}
}
}
}
Loading