From 25b9945c05d00f2a2fdb801c16763f4e623a9486 Mon Sep 17 00:00:00 2001 From: VronzeWook Date: Wed, 15 Jan 2025 14:24:51 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat:#138-MainView=20Refresh=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spha/Spha/Views/Home/MainView.swift | 220 +++++++++++++++------------- 1 file changed, 122 insertions(+), 98 deletions(-) diff --git a/Spha/Spha/Views/Home/MainView.swift b/Spha/Spha/Views/Home/MainView.swift index 8fff53e..f83946d 100644 --- a/Spha/Spha/Views/Home/MainView.swift +++ b/Spha/Spha/Views/Home/MainView.swift @@ -7,6 +7,7 @@ struct MainView: View { @State private var introOpacity = 0.0 @State private var isFirstLaunch: Bool = !UserDefaults.standard.bool(forKey: "hasLaunchedBefore") @State private var isBreathingViewPresented = false + @State private var isLoading = false var body: some View { ZStack { @@ -14,119 +15,120 @@ struct MainView: View { Color.backgroundGB .edgesIgnoringSafeArea(.all) - // 메인 화면 요소 - VStack{ - HStack{ - Spacer() - - Button { - router.push(view: .dailyStatisticsView) - } label: { - Image(systemName: "chart.bar.fill") - .resizable() - .frame(width: 28, height: 20) - .foregroundStyle(Color.buttonGraph) + ScrollView { + VStack{ + HStack{ + Spacer() + + Button { + router.push(view: .dailyStatisticsView) + } label: { + Image(systemName: "chart.bar.fill") + .resizable() + .frame(width: 28, height: 20) + .foregroundStyle(Color.buttonGraph) + } + .padding(.trailing, 8) } - .padding(.trailing, 8) - } - .padding(.top, 16) - .padding(.horizontal, 16) - - Spacer() - - HStack{ - Text("현재 마음구슬 상태") - .customFont(.caption_0) - .foregroundStyle(.white) + .padding(.top, 32) + .padding(.horizontal, 16) - Button { - router.push(view: .mainInfoView) - } label: { - Image(systemName: "info.circle") - .resizable() - .frame(width: 15, height: 15) - .foregroundStyle(.white) - } + Spacer() - } - - Text("\(String(describing: viewModel.mindDustLvDescription))") - .customFont(.title_1) - .foregroundStyle( - viewModel.isHRVRecordedToday ? - .white : Color.gray0 - ) - .bold() - .padding(.top, 8) - - Spacer() - - MP4PlayerView(videoURLString: viewModel.mindDustLevel) - .frame(width: 300, height: 300) - .padding(.bottom, 16) - - - HStack{ - VStack{ - HStack{ - Text("\(viewModel.recommendedCount)") - .customFont(.title_0) - .foregroundStyle(.white) - .bold() - - Text("회") - .customFont(.caption_0) + HStack{ + Text("현재 마음구슬 상태") + .customFont(.caption_0) + .foregroundStyle(.white) + + Button { + router.push(view: .mainInfoView) + } label: { + Image(systemName: "info.circle") + .resizable() + .frame(width: 15, height: 15) .foregroundStyle(.white) - .bold() } - .padding(.bottom, 2) - Text("권장 청소 횟수") - .customFont(.caption_1) - .foregroundStyle(.gray) } - Rectangle() - .frame(width:1, height: 45) - .foregroundStyle(.gray) - .padding(.horizontal, 24) + Text("\(String(describing: viewModel.mindDustLvDescription))") + .customFont(.title_1) + .foregroundStyle( + viewModel.isHRVRecordedToday ? + .white : Color.gray0 + ) + .bold() + .padding(.top, 8) - VStack{ - HStack{ - Text("\(viewModel.completedCount)") - .customFont(.title_0) - .foregroundStyle(.white) - .bold() + Spacer() + + MP4PlayerView(videoURLString: viewModel.mindDustLevel) + .frame(width: 300, height: 300) + .padding(.bottom, 16) + + + HStack{ + VStack{ + HStack{ + Text("\(viewModel.recommendedCount)") + .customFont(.title_0) + .foregroundStyle(.white) + .bold() + + Text("회") + .customFont(.caption_0) + .foregroundStyle(.white) + .bold() + } + .padding(.bottom, 2) - Text("회") - .customFont(.caption_0) - .foregroundStyle(.white) - .bold() + Text("권장 청소 횟수") + .customFont(.caption_1) + .foregroundStyle(.gray) } - .padding(.bottom, 2) - Text("실행한 청소 횟수") - .customFont(.caption_1) + Rectangle() + .frame(width:1, height: 45) .foregroundStyle(.gray) + .padding(.horizontal, 24) + + VStack{ + HStack{ + Text("\(viewModel.completedCount)") + .customFont(.title_0) + .foregroundStyle(.white) + .bold() + + Text("회") + .customFont(.caption_0) + .foregroundStyle(.white) + .bold() + } + .padding(.bottom, 2) + + Text("실행한 청소 횟수") + .customFont(.caption_1) + .foregroundStyle(.gray) + } } - } - .padding(.bottom, 12) - - Spacer() - - Button { - isBreathingViewPresented.toggle() + .padding(.bottom, 12) + + Spacer() - } label: { - // 임시 버튼 라벨 - Image("mainButton") - .resizable() - .frame(width: 90, height: 90) - .foregroundStyle(.gray) + Button { + isBreathingViewPresented.toggle() + } label: { + // 임시 버튼 라벨 + Image("mainButton") + .resizable() + .frame(width: 90, height: 90) + .foregroundStyle(.gray) + } + .padding(.top, 40) } - - Spacer() - + } + .refreshable { + triggerRefresh() } // OnboardingStartView 오버레이 @@ -135,11 +137,17 @@ struct MainView: View { .transition(.opacity) // 페이드 효과 .zIndex(1) // 항상 최상위에 위치 } + + // 로딩 중 프로그레스 바 + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()).foregroundColor(.white) + .background(Color.black.opacity(0.5).edgesIgnoringSafeArea(.all)) + } } .sheet(isPresented: $isBreathingViewPresented) { BreathingMainView(breathManager: BreathingMainViewModel()) } - .onAppear { if !isFirstLaunch { viewModel.updateTodayRecord() @@ -150,6 +158,22 @@ struct MainView: View { } } + private func triggerRefresh() { + // 햅틱 발생 + let generator = UIImpactFeedbackGenerator(style: .light) + generator.impactOccurred() + + // 로딩 상태 활성화 + isLoading = true + + // 데이터 업데이트 실행 + viewModel.updateTodayRecord() + + // 로딩 상태 비활성화 (딜레이 시뮬레이션) + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + isLoading = false + } + } } #Preview { From f3c168a5a816610c03fc46dfa42b492eb3e5f22f Mon Sep 17 00:00:00 2001 From: VronzeWook Date: Wed, 15 Jan 2025 14:32:54 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Feat:#138-MainView=20Foreground=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=20Refresh=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spha/Spha/Views/Home/MainView.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Spha/Spha/Views/Home/MainView.swift b/Spha/Spha/Views/Home/MainView.swift index f83946d..4cb8e35 100644 --- a/Spha/Spha/Views/Home/MainView.swift +++ b/Spha/Spha/Views/Home/MainView.swift @@ -2,6 +2,8 @@ import SwiftUI struct MainView: View { @EnvironmentObject var router: RouterManager + @Environment(\.scenePhase) private var scenePhase + @StateObject private var viewModel = MainViewModel(HealthKitManager(), MindfulSessionManager()) @State private var introOpacity = 0.0 @@ -124,7 +126,7 @@ struct MainView: View { .frame(width: 90, height: 90) .foregroundStyle(.gray) } - .padding(.top, 40) + .padding(.top, 48) } } .refreshable { @@ -156,6 +158,11 @@ struct MainView: View { .onChange(of: self.isFirstLaunch) { oldValue, newValue in viewModel.updateTodayRecord() } + .onChange(of: scenePhase) { _, newPhase in // 추가: 앱 상태 변화 감지 + if newPhase == .active { // 포그라운드로 복귀 시 + viewModel.updateTodayRecord() + } + } } private func triggerRefresh() { From 5e7afd8e02f10c0ce7019a383c688c64c7b9f04c Mon Sep 17 00:00:00 2001 From: VronzeWook Date: Mon, 20 Jan 2025 14:32:06 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Feat:#138-=ED=99=94=EB=A9=B4=20=EA=B0=84?= =?UTF-8?q?=EA=B2=A9=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spha/Spha/Views/Home/MainView.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Spha/Spha/Views/Home/MainView.swift b/Spha/Spha/Views/Home/MainView.swift index 4cb8e35..f33c7bf 100644 --- a/Spha/Spha/Views/Home/MainView.swift +++ b/Spha/Spha/Views/Home/MainView.swift @@ -27,12 +27,13 @@ struct MainView: View { } label: { Image(systemName: "chart.bar.fill") .resizable() - .frame(width: 28, height: 20) + .frame(width: 28, height: 22) .foregroundStyle(Color.buttonGraph) } .padding(.trailing, 8) } .padding(.top, 32) + .padding(.bottom, 24) .padding(.horizontal, 16) Spacer() @@ -60,13 +61,13 @@ struct MainView: View { .white : Color.gray0 ) .bold() - .padding(.top, 8) + .padding(.top, 16) Spacer() MP4PlayerView(videoURLString: viewModel.mindDustLevel) .frame(width: 300, height: 300) - .padding(.bottom, 16) + .padding(.bottom, 32) HStack{ @@ -113,7 +114,7 @@ struct MainView: View { .foregroundStyle(.gray) } } - .padding(.bottom, 12) + //.padding(.bottom, 12) Spacer()