From cfb37d07dbd756634272d948102af85e10323c2b Mon Sep 17 00:00:00 2001 From: ParkSeongGeun Date: Mon, 20 Oct 2025 22:34:51 +0900 Subject: [PATCH 1/2] [Feat] Create InfoView --- .../Image/InfoImage.imageset/Contents.json | 21 ++ .../Image/InfoImage.imageset/InfoImage.png | Bin 0 -> 5710 bytes .../Core/Presentation/Help/InfoView.swift | 105 +++++- .../Core/Presentation/Home/HomeView.swift | 333 +++++++++--------- 4 files changed, 290 insertions(+), 169 deletions(-) create mode 100644 ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/Contents.json create mode 100644 ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/InfoImage.png diff --git a/ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/Contents.json b/ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/Contents.json new file mode 100644 index 0000000..408c4f1 --- /dev/null +++ b/ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "InfoImage.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/InfoImage.png b/ComfortableMove/ComfortableMove/App/Resources/Assets.xcassets/Image/InfoImage.imageset/InfoImage.png new file mode 100644 index 0000000000000000000000000000000000000000..c690445b57ba8e58965f049bc9e5b501d4a63406 GIT binary patch literal 5710 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 Ai~s-t literal 0 HcmV?d00001 diff --git a/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift b/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift index fc624f9..95ce110 100644 --- a/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift +++ b/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift @@ -8,8 +8,111 @@ import SwiftUI struct InfoView: View { + @Environment(\.dismiss) private var dismiss + private let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0" + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + VStack(spacing: 0) { + Spacer() + .frame(height: 60) + // 상단 이미지 영역 + Image("InfoImage") + .resizable() + .scaledToFit() + .frame(width: 100, height: 170) + .padding(.bottom, 100) + + // 하단 리스트 영역 + VStack(spacing: 0) { + // 버전 정보 + HStack { + Text("버전") + .moveFont(.homeSubTitle) + .foregroundColor(.mainPalette2) + Spacer() + Text("v \(appVersion)") + .moveFont(.homeSubTitle) + .foregroundColor(.gray) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .background(Color.white) + + Divider() + .padding(.leading, 20) + + // 앱 문의 + Button(action: { + if let url = URL(string: "https://github.com/ParkSeongGeun") { + UIApplication.shared.open(url) + } + }) { + HStack { + Text("앱 문의") + .moveFont(.homeSubTitle) + .foregroundColor(.mainPalette2) + Spacer() + Image(systemName: "chevron.right") + .moveFont(.homeSubTitle) + .foregroundColor(.gray) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .background(Color.white) + } + + Divider() + .padding(.leading, 20) + + // 개인정보 처리 방침 및 이용약관 + Button(action: { + if let url = URL(string: "https://github.com/ParkSeongGeun") { + UIApplication.shared.open(url) + } + }) { + HStack { + Text("개인정보 처리 방침 및 이용약관") + .moveFont(.homeSubTitle) + .foregroundColor(.mainPalette2) + Spacer() + Image(systemName: "chevron.right") + .moveFont(.homeSubTitle) + .foregroundColor(.gray) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .background(Color.white) + } + } + .background(Color.white) + .cornerRadius(20) + .padding(.horizontal, 20) + + Spacer() + } + .background(Color("BFPrimaryColor")) + .navigationBarTitleDisplayMode(.inline) + .navigationBarBackButtonHidden(true) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + HStack(spacing: 8) { + Button(action: { + dismiss() + }) { + Image(systemName: "chevron.left") + .font(.title2) + .foregroundColor(.white) + } + + Text("앱정보") + .moveFont(.homeMediumTitle) + .foregroundColor(.white) + } + } + } + .toolbarBackground(Color("BFPrimaryColor"), for: .navigationBar) + .toolbarBackground(.visible, for: .navigationBar) + .toolbarColorScheme(.dark, for: .navigationBar) } } diff --git a/ComfortableMove/ComfortableMove/Core/Presentation/Home/HomeView.swift b/ComfortableMove/ComfortableMove/Core/Presentation/Home/HomeView.swift index e0a4bb3..10f0493 100644 --- a/ComfortableMove/ComfortableMove/Core/Presentation/Home/HomeView.swift +++ b/ComfortableMove/ComfortableMove/Core/Presentation/Home/HomeView.swift @@ -11,20 +11,19 @@ struct HomeView: View { @StateObject private var busStopManager = BusStopManager() @StateObject private var locationManager = LocationManager() @StateObject private var bluetoothManager = BluetoothManager() - + @State private var selectedRouteId: Int? @State private var busArrivals: [Int: String] = [:] // routeId: 도착메시지 @State private var isLoadingArrivals = false - + // Alert 상태 @State private var showConfirmAlert = false @State private var showSuccessAlert = false @State private var showFailureAlert = false - + // 화면 표시 상태 @State private var showHelpPage = false - @State private var showInfoView = false - + // MARK: - Dummy Data private var dummyStop: StopWithRoutes { StopWithRoutes( @@ -39,188 +38,186 @@ struct HomeView: View { id: 1 ) } - + private var displayStop: StopWithRoutes? { busStopManager.nearestStop ?? dummyStop } - + var body: some View { - VStack(spacing: 0) { - // 상단 헤더 + NavigationStack { VStack(spacing: 0) { - // 상태바 영역 - Rectangle() - .fill(Color("BFPrimaryColor")) - .frame(height: 44) - - // 네비게이션 헤더 - HStack { - Image("HomeTitle") - .resizable() - .scaledToFit() - .frame(height: 28) - - Spacer() - - HStack(spacing: 10) { - Button(action: { - showHelpPage = true - }) { - Image(systemName: "questionmark.circle") - .font(.title2) - .foregroundColor(.white) - } - - Button(action: { - showInfoView = true - }) { - Image(systemName: "gearshape") - .font(.title2) - .foregroundColor(.white) - } - } - } - .padding(.horizontal, 24) - .padding(.vertical, 16) - .background(Color("BFPrimaryColor")) - } - - Spacer() - - VStack(spacing: 30) { - // 중앙 버튼 - Button(action: { - if selectedRouteId != nil { - showConfirmAlert = true - } - }) { - ZStack { - Image("buttonImage") + // 상단 헤더 + VStack(spacing: 0) { + // 상태바 영역 + Rectangle() + .fill(Color("BFPrimaryColor")) + .frame(height: 44) + + // 네비게이션 헤더 + HStack { + Image("HomeTitle") .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 240, height: 240) + .scaledToFit() + .frame(height: 28) + + Spacer() + + HStack(spacing: 10) { + Button(action: { + showHelpPage = true + }) { + Image(systemName: "questionmark.circle") + .font(.title2) + .foregroundColor(.white) + } + + NavigationLink(destination: InfoView()) { + Image(systemName: "gearshape") + .font(.title2) + .foregroundColor(.white) + } + } } + .padding(.horizontal, 24) + .padding(.vertical, 16) + .background(Color("BFPrimaryColor")) } - .padding(.top, 40) - // 버튼 아래 텍스트 - Text("버스 선택 후, 알림을 울려주세요!") - .moveFont(.homeSubTitle) - .foregroundColor(.white) - } - - List { - // 첫 번째 칸 - 정류장 정보 - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(displayStop?.stopName ?? "정류장을 찾는 중...") - .moveFont(.homeSubTitle) - .foregroundColor(.black) - - Text(displayStop?.direction ?? "") - .moveFont(.caption) - .foregroundColor(.gray) - } - - Spacer() - + Spacer() + + VStack(spacing: 30) { + // 중앙 버튼 Button(action: { - refreshBusArrivals() + if selectedRouteId != nil { + showConfirmAlert = true + } }) { - Image(systemName: "arrow.clockwise") - .font(.title2) - .foregroundColor(.gray) - .rotationEffect(.degrees(isLoadingArrivals ? 360 : 0)) - .animation(isLoadingArrivals ? .linear(duration: 1).repeatForever(autoreverses: false) : .default, value: isLoadingArrivals) + ZStack { + Image("buttonImage") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 240, height: 240) + } } - .disabled(isLoadingArrivals) + .padding(.top, 40) + + // 버튼 아래 텍스트 + Text("버스 선택 후, 알림을 울려주세요!") + .moveFont(.homeSubTitle) + .foregroundColor(.white) } - .padding(.vertical, 4) - - // 버스 노선들 - if let routes = displayStop?.routes { - ForEach(routes, id: \.routeId) { route in - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(route.routeName) - .moveFont(.homeSubTitle) - .foregroundColor(.blue) - .fontWeight(.bold) - - if let arrivalMsg = busArrivals[route.routeId] { - Text(arrivalMsg) - .moveFont(.caption) - .foregroundColor(.gray) + + List { + // 첫 번째 칸 - 정류장 정보 + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(displayStop?.stopName ?? "정류장을 찾는 중...") + .moveFont(.homeSubTitle) + .foregroundColor(.black) + + Text(displayStop?.direction ?? "") + .moveFont(.caption) + .foregroundColor(.gray) + } + + Spacer() + + Button(action: { + refreshBusArrivals() + }) { + Image(systemName: "arrow.clockwise") + .font(.title2) + .foregroundColor(.gray) + .rotationEffect(.degrees(isLoadingArrivals ? 360 : 0)) + .animation(isLoadingArrivals ? .linear(duration: 1).repeatForever(autoreverses: false) : .default, value: isLoadingArrivals) + } + .disabled(isLoadingArrivals) + } + .padding(.vertical, 4) + + // 버스 노선들 + if let routes = displayStop?.routes { + ForEach(routes, id: \.routeId) { route in + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(route.routeName) + .moveFont(.homeSubTitle) + .foregroundColor(.blue) + .fontWeight(.bold) + + if let arrivalMsg = busArrivals[route.routeId] { + Text(arrivalMsg) + .moveFont(.caption) + .foregroundColor(.gray) + } } + + Spacer() + + Button(action: { + selectedRouteId = route.routeId + }) { + Circle() + .fill(selectedRouteId == route.routeId ? Color.blue : Color.gray.opacity(0.3)) + .frame(width: 24, height: 24) + .overlay( + Image(systemName: "checkmark") + .font(.system(size: 12, weight: .bold)) + .foregroundColor(.white) + .opacity(selectedRouteId == route.routeId ? 1 : 0) + ) + } + .buttonStyle(PlainButtonStyle()) } - - Spacer() - - Button(action: { - selectedRouteId = route.routeId - }) { - Circle() - .fill(selectedRouteId == route.routeId ? Color.blue : Color.gray.opacity(0.3)) - .frame(width: 24, height: 24) - .overlay( - Image(systemName: "checkmark") - .font(.system(size: 12, weight: .bold)) - .foregroundColor(.white) - .opacity(selectedRouteId == route.routeId ? 1 : 0) - ) - } - .buttonStyle(PlainButtonStyle()) + .padding(.vertical, 8) } - .padding(.vertical, 8) } } + .listStyle(InsetGroupedListStyle()) + .scrollContentBackground(.hidden) + .padding(.top, 30) + + Spacer() } - .listStyle(InsetGroupedListStyle()) - .scrollContentBackground(.hidden) - .padding(.top, 30) - - Spacer() - } - .background(Color("BFPrimaryColor")) - .ignoresSafeArea(.all, edges: .top) - .onAppear { - locationManager.requestPermission() - } - .onChange(of: locationManager.currentLocation) { newLocation in - if let location = newLocation { - busStopManager.findNearestStop(userLocation: location) + .background(Color("BFPrimaryColor")) + .ignoresSafeArea(.all, edges: .top) + .onAppear { + locationManager.requestPermission() } - } - .onChange(of: busStopManager.nearestStop) { newStop in - if newStop != nil { - refreshBusArrivals() + .onChange(of: locationManager.currentLocation) { newLocation in + if let location = newLocation { + busStopManager.findNearestStop(userLocation: location) + } } - } - .alert(isPresented: $showConfirmAlert) { - Alert( - title: Text("\(selectedBusName)버스에 배려석 알림을 전송하시겠습니까?"), - primaryButton: .destructive(Text("취소")), - secondaryButton: .default(Text("확인")) { - sendCourtesySeatNotification() + .onChange(of: busStopManager.nearestStop) { newStop in + if newStop != nil { + refreshBusArrivals() } + } + .alert(isPresented: $showConfirmAlert) { + Alert( + title: Text("\(selectedBusName)버스에 배려석 알림을 전송하시겠습니까?"), + primaryButton: .destructive(Text("취소")), + secondaryButton: .default(Text("확인")) { + sendCourtesySeatNotification() + } + ) + } + .alert("알림 전송 완료", isPresented: $showSuccessAlert) { + Button("확인", role: .cancel) { } + } + .alert("버스 배려석 알림 전송에 실패하였습니다.", isPresented: $showFailureAlert) { + Button("확인", role: .cancel) { } + } message: { + Text("다시 한번 시도해주세요.") + } + .overlay( + showHelpPage ? HelpPageView(isPresented: $showHelpPage) : nil ) - } - .alert("알림 전송 완료", isPresented: $showSuccessAlert) { - Button("확인", role: .cancel) { } - } - .alert("버스 배려석 알림 전송에 실패하였습니다.", isPresented: $showFailureAlert) { - Button("확인", role: .cancel) { } - } message: { - Text("다시 한번 시도해주세요.") - } - .overlay( - showHelpPage ? HelpPageView(isPresented: $showHelpPage) : nil - ) - .fullScreenCover(isPresented: $showInfoView) { - InfoView() + .navigationBarHidden(true) } } - + // MARK: - Computed Properties private var selectedBusName: String { guard let routeId = selectedRouteId, @@ -230,7 +227,7 @@ struct HomeView: View { } return selectedRoute.routeName } - + // MARK: - 배려석 알림 전송 private func sendCourtesySeatNotification() { bluetoothManager.sendCourtesySeatNotification(busNumber: selectedBusName) { success in @@ -241,13 +238,13 @@ struct HomeView: View { } } } - + // MARK: - 버스 도착 정보 새로고침 private func refreshBusArrivals() { guard let stop = busStopManager.nearestStop else { return } - + isLoadingArrivals = true - + Task { await withTaskGroup(of: (Int, String?).self) { group in for route in stop.routes { @@ -259,12 +256,12 @@ struct HomeView: View { return (route.routeId, arrival) } } - + for await (routeId, arrival) in group { busArrivals[routeId] = arrival ?? "도착 정보 없음" } } - + isLoadingArrivals = false } } From 3ba704a7979de5088c4efff25d2115f65b36d702 Mon Sep 17 00:00:00 2001 From: ParkSeongGeun Date: Mon, 20 Oct 2025 22:38:41 +0900 Subject: [PATCH 2/2] [Fix] pdate InfoView navigation bar appearance --- .../Core/Presentation/Help/InfoView.swift | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift b/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift index 95ce110..72fba37 100644 --- a/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift +++ b/ComfortableMove/ComfortableMove/Core/Presentation/Help/InfoView.swift @@ -92,24 +92,8 @@ struct InfoView: View { } .background(Color("BFPrimaryColor")) .navigationBarTitleDisplayMode(.inline) - .navigationBarBackButtonHidden(true) - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - HStack(spacing: 8) { - Button(action: { - dismiss() - }) { - Image(systemName: "chevron.left") - .font(.title2) - .foregroundColor(.white) - } - - Text("앱정보") - .moveFont(.homeMediumTitle) - .foregroundColor(.white) - } - } - } + .navigationBarBackButtonHidden(false) + .navigationTitle("앱정보") .toolbarBackground(Color("BFPrimaryColor"), for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar)