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

[SCRUM-102] mvp2차 지현 QA - 1 #63

Merged
merged 9 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 7 additions & 3 deletions Projects/Domain/CatService/Interface/Model/CatTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import DesignSystem

public protocol CatTemplate: Equatable {
var baseInfo: Cat { get }
var defaultName: String { get }
var keyword: String { get }
var keywordImage: Image { get }
var rivTriggerName: String { get }
Expand All @@ -30,7 +31,8 @@ public protocol CatTemplate: Equatable {

struct CheeseCat: CatTemplate {
public let baseInfo: Cat


var defaultName: String = "치즈냥"
var keyword: String = "응원"
var keywordImage: Image = DesignSystemAsset.Image._16Star.swiftUIImage
var rivTriggerName: String = "Click_Cheese Cat"
Expand All @@ -56,7 +58,8 @@ struct CheeseCat: CatTemplate {

struct BlackCat: CatTemplate {
public let baseInfo: Cat


var defaultName: String = "까만냥"
var keyword: String = "긍정"
var keywordImage: Image = DesignSystemAsset.Image._16Heart.swiftUIImage
var rivTriggerName: String = "Click_Black Cat"
Expand All @@ -82,7 +85,8 @@ struct BlackCat: CatTemplate {

struct ThreeColorCat: CatTemplate {
let baseInfo: Cat


var defaultName: String = "삼색냥"
var keyword: String = "자극"
var keywordImage: Image = DesignSystemAsset.Image._16Focus.swiftUIImage
var rivTriggerName: String = "Click_Calico Cat"
Expand Down
1 change: 1 addition & 0 deletions Projects/Domain/CatService/Interface/Model/SomeCat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public struct SomeCat: CatTemplate, Identifiable {
private var template: any CatTemplate

public var baseInfo: Cat { template.baseInfo }
public var defaultName: String { template.defaultName }
public var keyword: String { template.keyword }
public var keywordImage: Image { template.keywordImage }
public var rivTriggerName: String { template.rivTriggerName }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public struct NamingCatCore {
var tooltip: DownDirectionTooltip? = .init()
var catRiv: RiveViewModel = Rive.catRenameRiv(stateMachineName: "State Machine_Rename")

var height: CGFloat = .zero

public init(route: Route) {
self.route = route
}
Expand Down
71 changes: 41 additions & 30 deletions Projects/Feature/CatFeature/Sources/NamingCat/NamingCatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,55 +15,66 @@ import RiveRuntime
import DatadogRUM

public struct NamingCatView: View {
@Namespace var backgroundFrameID
@Bindable var store: StoreOf<NamingCatCore>

public init(store: StoreOf<NamingCatCore>) {
self.store = store
}

public var body: some View {
NavigationContainer(
title: Text("고양이 이름짓기"),
style: .navigation
) {
VStack(spacing: 40) {
Spacer()

store.catRiv.view()
.setTooltipTarget(tooltip: DownDirectionTooltip.self)
.frame(minHeight: 200, maxHeight: 240)
ScrollView {
VStack(spacing: Alias.Spacing.xLarge) {
Spacer(minLength: 0)

store.catRiv.view()
.setTooltipTarget(tooltip: DownDirectionTooltip.self)
.frame(minHeight: 200, maxHeight: 240)

VStack(spacing: Alias.Spacing.small) {
HStack {
Text("내 고양이의 이름")
.font(Typography.subBodyR)
.foregroundStyle(Alias.Color.Text.secondary)
.padding(.leading, Alias.Spacing.xSmall)
Spacer()
VStack(spacing: Alias.Spacing.small) {
HStack {
Text("내 고양이의 이름")
.font(Typography.subBodyR)
.foregroundStyle(Alias.Color.Text.secondary)
.padding(.leading, Alias.Spacing.xSmall)
Spacer()
}
InputField(
placeholder: store.selectedCat?.defaultName ?? "",
text: $store.text,
fieldError: $store.inputFieldError,
submitLabel: .done
)
}
InputField(
placeholder: store.selectedCat?.baseInfo.name ?? "",
text: $store.text,
fieldError: $store.inputFieldError
)
}

Spacer()

Button("확인") {
store.send(.namedButtonTapped)

Spacer(minLength: 0)

Button("확인") {
store.send(.namedButtonTapped)
}
.buttonStyle(.box(level: .primary, size: .large, width: .low))
.disabled(store.isButtonDisabled)
.padding(.bottom, Alias.Spacing.small)
}
.buttonStyle(.box(level: .primary, size: .large, width: .low))
.disabled(store.isButtonDisabled)
.padding(.bottom, Alias.Spacing.small)
.padding(.horizontal, Alias.Spacing.xLarge)
.frame(minHeight: store.height - 56)
}
.padding(.horizontal, Alias.Spacing.xLarge)
}
.scrollDismissesKeyboard(.interactively)
.tooltipDestination(tooltip: $store.tooltip.sending(\.setTooltip))
.background {
Alias.Color.Background.primary
.ignoresSafeArea()
}
.tooltipDestination(tooltip: $store.tooltip.sending(\.setTooltip))
.setFrameMeasure(space: .local, identifier: backgroundFrameID)
.getFrameMeasure { value in
guard let frame = value[backgroundFrameID] else { return }
store.height = frame.height
}
.onAppear {
store.send(.onAppear)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public struct SelectCatView: View {
HStack {
ForEach(store.catList) { cat in
Button(
title: LocalizedStringKey(cat.baseInfo.name),
title: LocalizedStringKey(cat.defaultName),
subtitle: LocalizedStringKey(cat.keyword),
rightIcon: cat.keywordImage,
action: { store.send(.selectCat(cat)) }
Expand Down
36 changes: 27 additions & 9 deletions Projects/Feature/MyPageFeature/Sources/MyPage/MyPageCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public struct MyPageCore {
var isLiveActivityOn: Bool = false
var isNetworkConnected: Bool = false
var dialog: DefaultDialog?
var lastToggledAlarmType: AlarmType?
@Presents var myCat: MyCatCore.State?

public init() {}
Expand All @@ -44,13 +45,19 @@ public struct MyPageCore {
case timerAlarmToggleButtonTapped(Bool)
case disturbAlarmToggleButtonTapped(Bool)
case liveActivityToggleButtonTapped(Bool)
case scenePhaseActive
case sendFeedbackButtonTapped
case _goToNotificationSettings
case _goToNotificationSettings(AlarmType?)
case _fetchNetworkConntection(Bool)
case myCat(PresentationAction<MyCatCore.Action>)
case binding(BindingAction<State>)
}


public enum AlarmType {
case timer
case disturb
}

@Dependency(APIClient.self) var apiClient
@Dependency(UserService.self) var userService
@Dependency(UserDefaultsClient.self) var userDefaultsClient
Expand All @@ -73,6 +80,7 @@ public struct MyPageCore {
private func core(state: inout State, action: Action) -> EffectOf<Self> {
switch action {
case .onAppear:
// TODO: userDefault get bool 은 옵셔널 값이 아니어서, 다른 방법을 사용해서 default setting 값 부여해야할듯
state.isTimerAlarmOn = getTimerAlarm(userDefaultsClient: self.userDefaultsClient)
state.isDisturbAlarmOn = getDisturbAlarm(userDefaultsClient: self.userDefaultsClient)
state.isLiveActivityOn = getLiveActivityState(userDefaultsClient: self.userDefaultsClient)
Expand Down Expand Up @@ -102,7 +110,7 @@ public struct MyPageCore {
} else {
await send(.set(\.isTimerAlarmOn, false))
let notificationSettingDialog = turnOnNotificationSettingDialog {
await send(._goToNotificationSettings)
await send(._goToNotificationSettings(.timer))
}
await send(.set(\.dialog, notificationSettingDialog))
}
Expand All @@ -120,15 +128,24 @@ public struct MyPageCore {
} else {
await send(.set(\.isDisturbAlarmOn, false))
let notificationSettingDialog = turnOnNotificationSettingDialog {
await send(._goToNotificationSettings)
await send(._goToNotificationSettings(.disturb))
}
await send(.set(\.dialog, notificationSettingDialog))
}
} else {
await send(.set(\.isDisturbAlarmOn, false))
}
}


case .scenePhaseActive:
return .run { [type = state.lastToggledAlarmType] send in
let settings = await userNotificationClient.getNotificationSettings()
if settings.authorizationStatus == .authorized {
await send(.set(type == .timer ? \.isTimerAlarmOn : \.isDisturbAlarmOn, true))
}
await send(.set(\.lastToggledAlarmType, nil))
}

case let .liveActivityToggleButtonTapped(isOn):
return .run { send in
if isOn {
Expand All @@ -138,22 +155,23 @@ public struct MyPageCore {
} else {
await send(.set(\.isLiveActivityOn, false))
let notificationSettingDialog = turnOnLiveActivitySettingDialog {
await send(._goToNotificationSettings)
await send(._goToNotificationSettings(nil))
}
await send(.set(\.dialog, notificationSettingDialog))
}
} else {
await send(.set(\.isLiveActivityOn, false))
}
}

case .sendFeedbackButtonTapped:
guard let feedbackURL = URL(string: "https://forms.gle/wEUPH9Tvxgua4hCZ9") else { return .none }
return .run { _ in
await self.openURL(feedbackURL)
}

case ._goToNotificationSettings:
case let ._goToNotificationSettings(type):
state.lastToggledAlarmType = type
guard let notificationSettingsURL = URL(
string: UIApplication.openNotificationSettingsURLString
) else {
Expand Down Expand Up @@ -204,7 +222,7 @@ extension MyPageCore {
private func turnOnNotificationSettingDialog(action: @escaping () async -> Void) -> DefaultDialog {
return DefaultDialog(
title: "설정에서 알림을 켜주세요",
subTitle: "모하냥 앱의 알림 표시를 허용하면 Push 알림을 받을 수 있어요. 지금 설정하시겠어요?",
subTitle: "알림 표시를 허용하면 Push 알림을 받을 수 있어요.",
firstButton: .init(title: "다음에"),
secondButton: .init(
title: "설정으로 이동",
Expand Down
64 changes: 40 additions & 24 deletions Projects/Feature/MyPageFeature/Sources/MyPage/MyPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ComposableArchitecture
import DatadogRUM

public struct MyPageView: View {
@Environment(\.scenePhase) private var scenePhase
@Bindable var store: StoreOf<MyPageCore>

public init(store: StoreOf<MyPageCore>) {
Expand Down Expand Up @@ -43,11 +44,6 @@ public struct MyPageView: View {
}

StatisticSectionView(isNetworkConnected: $store.isNetworkConnected)
.padding(.all, Alias.Spacing.xLarge)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.medium)
.foregroundStyle(Alias.Color.Background.secondary)
)

VStack(spacing: Alias.Spacing.large) {
AlarmSectionView(
Expand Down Expand Up @@ -104,6 +100,11 @@ public struct MyPageView: View {
.task {
await store.send(.task).finish()
}
.onChange(of: scenePhase) {
if scenePhase == .active {
store.send(.scenePhaseActive)
}
}
.onAppear {
store.send(.onAppear)
}
Expand Down Expand Up @@ -137,29 +138,44 @@ struct StatisticSectionView: View {
@Binding var isNetworkConnected: Bool

var body: some View {
ZStack {
VStack(spacing: Alias.Spacing.medium) {
Spacer()
if isNetworkConnected {
DesignSystemAsset.Image.imgUpdateStatistics.swiftUIImage
} else {
DesignSystemAsset.Image.imgOfflineStatistics.swiftUIImage
}
VStack(spacing: Alias.Spacing.xSmall) {
Text("통계 기능을 준비하고 있어요")
.font(Typography.header4)
.foregroundStyle(Alias.Color.Text.primary)
Text("집중시간을 모아보는 통계가\n곧업데이트될 예정이에요")
.font(Typography.subBodyR)
.foregroundStyle(Alias.Color.Text.secondary)
.multilineTextAlignment(.center)
}
Spacer()
VStack(spacing: Alias.Spacing.large) {
if isNetworkConnected {
content(
image: DesignSystemAsset.Image.imgUpdateStatistics.swiftUIImage,
title: "통계 기능을 준비하고 있어요",
subTitle: "집중시간을 모아보는 통계가\n곧업데이트될 예정이에요"
)
} else {
content(
image: DesignSystemAsset.Image.imgOfflineStatistics.swiftUIImage,
title: "지금은 통계를 확인할 수 없어요",
subTitle: "인터넷에 연결하면 통계를 볼 수 있어요"
)
}
}
.frame(maxWidth: .infinity)
.frame(minHeight: 375)
.padding(.all, Alias.Spacing.xxLarge)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.medium)
.foregroundStyle(Alias.Color.Background.secondary)
)
}

@ViewBuilder private func content(image: Image, title: String, subTitle: String) -> some View {
image.resizable()
.frame(width: 96, height: 96)

VStack(spacing: Alias.Spacing.xSmall) {
Text(title)
.font(Typography.bodySB)
.foregroundStyle(Alias.Color.Text.secondary)
Text(subTitle)
.font(Typography.subBodyR)
.foregroundStyle(Alias.Color.Text.secondary)
.multilineTextAlignment(.center)
}
}

}

struct AlarmSectionView: View {
Expand Down
Loading
Loading