Skip to content

Commit 9d991b2

Browse files
authored
Merge pull request #309 from Atcha-Project/env/dev
[Merge] Stage 환경 배포 및 QA 요청 (v1.9)
2 parents cd94823 + 416961a commit 9d991b2

File tree

53 files changed

+1730
-759
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1730
-759
lines changed

Atcha-iOS.xcodeproj/project.pbxproj

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@
151151
6DC3BF5E2E07123F00831470 /* IntroCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC3BF5D2E07123F00831470 /* IntroCell.swift */; };
152152
6DC3BF602E071F0900831470 /* LoginUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC3BF5F2E071F0900831470 /* LoginUseCase.swift */; };
153153
6DC3BF682E0721F300831470 /* LoginDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC3BF672E0721F300831470 /* LoginDTO.swift */; };
154+
6DC617A72F60EB1A002DD641 /* LocationSmoother.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC617A62F60EB1A002DD641 /* LocationSmoother.swift */; };
155+
6DC617A92F610238002DD641 /* HomeArrivalManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC617A82F610238002DD641 /* HomeArrivalManager.swift */; };
156+
6DC617AD2F62EB59002DD641 /* HomeRegistrationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC617AC2F62EB59002DD641 /* HomeRegistrationCoordinator.swift */; };
154157
6DD632B12E4F8A9F00C6A66E /* CheckServiceRegionRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD632B02E4F8A9F00C6A66E /* CheckServiceRegionRequest.swift */; };
155158
6DD632B62E52E23A00C6A66E /* ProximityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD632B52E52E23A00C6A66E /* ProximityManager.swift */; };
156159
6DD632B92E52E8E300C6A66E /* ProximityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD632B82E52E8E300C6A66E /* ProximityViewController.swift */; };
@@ -472,6 +475,9 @@
472475
6DC3BF5D2E07123F00831470 /* IntroCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroCell.swift; sourceTree = "<group>"; };
473476
6DC3BF5F2E071F0900831470 /* LoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginUseCase.swift; sourceTree = "<group>"; };
474477
6DC3BF672E0721F300831470 /* LoginDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginDTO.swift; sourceTree = "<group>"; };
478+
6DC617A62F60EB1A002DD641 /* LocationSmoother.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSmoother.swift; sourceTree = "<group>"; };
479+
6DC617A82F610238002DD641 /* HomeArrivalManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeArrivalManager.swift; sourceTree = "<group>"; };
480+
6DC617AC2F62EB59002DD641 /* HomeRegistrationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRegistrationCoordinator.swift; sourceTree = "<group>"; };
475481
6DD632B02E4F8A9F00C6A66E /* CheckServiceRegionRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckServiceRegionRequest.swift; sourceTree = "<group>"; };
476482
6DD632B52E52E23A00C6A66E /* ProximityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProximityManager.swift; sourceTree = "<group>"; };
477483
6DD632B82E52E8E300C6A66E /* ProximityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProximityViewController.swift; sourceTree = "<group>"; };
@@ -687,6 +693,7 @@
687693
6D1EE2D62E08E4AB00F7BBF1 /* HomeRegister */ = {
688694
isa = PBXGroup;
689695
children = (
696+
6DC617AB2F62EB4B002DD641 /* Coordinator */,
690697
6D1EE2D92E08E4E000F7BBF1 /* HomeRegisterViewController.swift */,
691698
6D1EE2DB2E08E4EA00F7BBF1 /* HomeRegisterViewModel.swift */,
692699
);
@@ -1109,6 +1116,21 @@
11091116
path = Login;
11101117
sourceTree = "<group>";
11111118
};
1119+
6DC617AA2F62E931002DD641 /* ChangeHome */ = {
1120+
isa = PBXGroup;
1121+
children = (
1122+
);
1123+
path = ChangeHome;
1124+
sourceTree = "<group>";
1125+
};
1126+
6DC617AB2F62EB4B002DD641 /* Coordinator */ = {
1127+
isa = PBXGroup;
1128+
children = (
1129+
6DC617AC2F62EB59002DD641 /* HomeRegistrationCoordinator.swift */,
1130+
);
1131+
path = Coordinator;
1132+
sourceTree = "<group>";
1133+
};
11121134
6DD632AE2E4F8A6600C6A66E /* SearchLocation */ = {
11131135
isa = PBXGroup;
11141136
children = (
@@ -1181,6 +1203,8 @@
11811203
6DADA5952EA09B9500CA9BE2 /* Amplitude */,
11821204
B61C448D2E3F57B600285A4B /* AlarmManager.swift */,
11831205
6DD632B72E52E8D000C6A66E /* Proximity */,
1206+
6DC617A62F60EB1A002DD641 /* LocationSmoother.swift */,
1207+
6DC617A82F610238002DD641 /* HomeArrivalManager.swift */,
11841208
);
11851209
path = Manager;
11861210
sourceTree = "<group>";
@@ -1305,6 +1329,7 @@
13051329
B65C12D82E042A320016D2F0 /* DIContainer */ = {
13061330
isa = PBXGroup;
13071331
children = (
1332+
6DC617AA2F62E931002DD641 /* ChangeHome */,
13081333
6D61ABE62F57174500111C9B /* Intro */,
13091334
B61C44962E40340C00285A4B /* LockScreen */,
13101335
6D2B8CB62E39C87F00608104 /* BusInfo */,
@@ -2144,6 +2169,7 @@
21442169
6DB7636D2E45C69400D06A49 /* AlarmRepository.swift in Sources */,
21452170
6DB7636F2E45C6D100D06A49 /* AlarmRepositoryImpl.swift in Sources */,
21462171
B65C12E22E042D400016D2F0 /* FetchUserUseCase.swift in Sources */,
2172+
6DC617AD2F62EB59002DD641 /* HomeRegistrationCoordinator.swift in Sources */,
21472173
B6EDD73C2E0D87F2006170DF /* FileStorageImpl.swift in Sources */,
21482174
B6793D4B2E3493D6001BE9F5 /* AtcahaInsetLabel.swift in Sources */,
21492175
6D2B8CB52E39AC7200608104 /* BusPositionInfoResponse.swift in Sources */,
@@ -2199,6 +2225,7 @@
21992225
B664018B2E2277A900A397AE /* PushAlarmOption.swift in Sources */,
22002226
6D26E0072F3C197F005097A4 /* SubwayInfoRepository.swift in Sources */,
22012227
B65C13082E057C590016D2F0 /* APIService.swift in Sources */,
2228+
6DC617A92F610238002DD641 /* HomeArrivalManager.swift in Sources */,
22022229
6D6879D02E4211B800E59C55 /* HomePatchRequest.swift in Sources */,
22032230
6D9283742E3AFF6A0090889B /* BusRouteCell.swift in Sources */,
22042231
6D73EB5F2E16120200F8DF8B /* CourseSearchViewModel.swift in Sources */,
@@ -2281,6 +2308,7 @@
22812308
6DADA5972EA09BA400CA9BE2 /* AmplitudeManager.swift in Sources */,
22822309
6DD632C22E544DB500C6A66E /* PushAlarmBottomView.swift in Sources */,
22832310
6D5E03D02E28853E0065AFBE /* CourseSearchResponse.swift in Sources */,
2311+
6DC617A72F60EB1A002DD641 /* LocationSmoother.swift in Sources */,
22842312
6D91A8E62E29F5BC0081BAFC /* CourseSettingViewModel.swift in Sources */,
22852313
6D26E0002F3C17C3005097A4 /* SubwayRealTimeInfoRequest.swift in Sources */,
22862314
B673C4912E0424FD00EE4AD0 /* SplashViewModel.swift in Sources */,
@@ -2460,7 +2488,7 @@
24602488
CODE_SIGN_IDENTITY = "Apple Development";
24612489
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
24622490
CODE_SIGN_STYLE = Manual;
2463-
CURRENT_PROJECT_VERSION = 15;
2491+
CURRENT_PROJECT_VERSION = 1;
24642492
DEVELOPMENT_TEAM = "";
24652493
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 23SCTLK482;
24662494
FRAMEWORK_SEARCH_PATHS = (
@@ -2483,7 +2511,7 @@
24832511
"$(inherited)",
24842512
"@executable_path/Frameworks",
24852513
);
2486-
MARKETING_VERSION = 1.7;
2514+
MARKETING_VERSION = 1.9;
24872515
PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS;
24882516
PRODUCT_NAME = "$(TARGET_NAME)";
24892517
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2507,7 +2535,7 @@
25072535
CODE_SIGN_ENTITLEMENTS = "Atcha-iOS/Atcha-iOS.entitlements";
25082536
CODE_SIGN_IDENTITY = "Apple Development";
25092537
CODE_SIGN_STYLE = Automatic;
2510-
CURRENT_PROJECT_VERSION = 15;
2538+
CURRENT_PROJECT_VERSION = 1;
25112539
DEVELOPMENT_TEAM = 23SCTLK482;
25122540
EXCLUDED_ARCHS = "";
25132541
FRAMEWORK_SEARCH_PATHS = (
@@ -2530,7 +2558,7 @@
25302558
"$(inherited)",
25312559
"@executable_path/Frameworks",
25322560
);
2533-
MARKETING_VERSION = 1.7;
2561+
MARKETING_VERSION = 1.9;
25342562
OTHER_SWIFT_FLAGS = "";
25352563
PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS;
25362564
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2555,7 +2583,7 @@
25552583
CODE_SIGN_IDENTITY = "Apple Development";
25562584
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
25572585
CODE_SIGN_STYLE = Manual;
2558-
CURRENT_PROJECT_VERSION = 15;
2586+
CURRENT_PROJECT_VERSION = 1;
25592587
DEVELOPMENT_TEAM = "";
25602588
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 23SCTLK482;
25612589
FRAMEWORK_SEARCH_PATHS = (
@@ -2578,7 +2606,7 @@
25782606
"$(inherited)",
25792607
"@executable_path/Frameworks",
25802608
);
2581-
MARKETING_VERSION = 1.7;
2609+
MARKETING_VERSION = 1.9;
25822610
PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS;
25832611
PRODUCT_NAME = "$(TARGET_NAME)";
25842612
PROVISIONING_PROFILE_SPECIFIER = "";

Atcha-iOS/App/DIContainer/Main/MainDIContainer.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ final class MainDIContainer {
4848
LoginDIContainer(apiService: apiService)
4949
}()
5050

51+
private lazy var homeRegisterDI: HomeRegisterDIContainer = {
52+
HomeRegisterDIContainer(apiService: apiService, locationStateHolder: locationStateHolder)
53+
}()
54+
5155
init(apiService: APIService, locationStateHolder: LocationStateHolder) {
5256
self.apiService = apiService
5357
self.locationStateHolder = locationStateHolder
@@ -128,3 +132,10 @@ extension MainDIContainer{
128132
}
129133
}
130134

135+
136+
// MARK: - HomeRegister
137+
extension MainDIContainer{
138+
func makeHomeRegisterDIContainer() -> HomeRegisterDIContainer {
139+
return homeRegisterDI
140+
}
141+
}

Atcha-iOS/Core/Manager/AlarmManager.swift

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final class AlarmManager {
3333
private var shouldKeepBackgroundAudio = false
3434
private var isPreviewing = false
3535
private var hapticEngine: CHHapticEngine?
36+
private var autoStopWorkItem: DispatchWorkItem?
3637

3738
// MARK: - Init
3839
private init() {
@@ -71,6 +72,8 @@ final class AlarmManager {
7172
/// 서버에서 받은 출발 시각 기준으로 1분 전에 반복 푸시/사운드/진동을 시작
7273
func startAlarm(title: String, body: String) {
7374
// 기존 알람 상태만 정리 (silent는 유지 or 다시 켜기)
75+
autoStopWorkItem?.cancel()
76+
autoStopWorkItem = nil
7477
stopAlarm(keepSilent: true)
7578
ensureBackgroundSilentRunning()
7679
applySavedVolumeForAlarmStart()
@@ -99,6 +102,9 @@ final class AlarmManager {
99102

100103
/// 완전 정지: 예약/타이머/진동/알림/오디오 모두 끊기
101104
func stopAlarm(keepSilent: Bool = false) {
105+
autoStopWorkItem?.cancel()
106+
autoStopWorkItem = nil
107+
102108
shouldKeepBackgroundAudio = false
103109
pendingStartWorkItem?.cancel()
104110
pendingStartWorkItem = nil
@@ -121,6 +127,7 @@ final class AlarmManager {
121127
}
122128

123129
print("알람 종료 (keepSilent = \(keepSilent))")
130+
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [AlarmNotificationID.autoStopInfo])
124131
}
125132

126133
func alarmInit() {
@@ -220,13 +227,19 @@ extension AlarmManager {
220227

221228
self.sendImmediateLocalPush(title: title, body: body)
222229
}
230+
231+
scheduleAutoStop()
223232
}
224233

225-
func sendImmediateLocalPush(title: String, body: String) {
234+
func sendImmediateLocalPush(title: String, body: String, playSound: Bool = false) {
226235
let content = UNMutableNotificationContent()
227236
content.title = title
228237
content.body = body
229-
content.sound = nil // 사운드는 직접 재생 중
238+
if playSound {
239+
content.sound = .default
240+
} else {
241+
content.sound = nil
242+
}
230243

231244
let request = UNNotificationRequest(
232245
identifier: UUID().uuidString,
@@ -593,3 +606,37 @@ extension AlarmManager {
593606
print("미리듣기 종료 (keep=\(shouldKeepBackgroundAudio))")
594607
}
595608
}
609+
610+
extension AlarmManager {
611+
private func scheduleAutoStop() {
612+
autoStopWorkItem?.cancel()
613+
614+
let content = UNMutableNotificationContent()
615+
content.title = "출발 알람이 자동 종료되었어요"
616+
content.body = "클릭해서 경로 재탐색하기"
617+
content.sound = .default
618+
619+
let request = UNNotificationRequest(
620+
identifier: AlarmNotificationID.autoStopInfo,
621+
content: content,
622+
trigger: UNTimeIntervalNotificationTrigger(timeInterval: 120.0, repeats: false)
623+
)
624+
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
625+
626+
// 2. 앱 내부의 정지 로직 및 팝업 신호 (포그라운드일 때 즉시, 백그라운드면 켜질 때 실행됨)
627+
let workItem = DispatchWorkItem { [weak self] in
628+
guard let self = self else { return }
629+
630+
// 음악/진동 정지
631+
self.stopAlarm(keepSilent: false) // 아예 무음까지 끄기
632+
633+
UserDefaults.standard.set(true, forKey: "isAlarmTimedOut")
634+
635+
// 메인 뷰에 타임아웃 팝업 띄우라고 신호
636+
NotificationCenter.default.post(name: NSNotification.Name("alarmDidTimeout"), object: nil)
637+
}
638+
639+
autoStopWorkItem = workItem
640+
DispatchQueue.main.asyncAfter(deadline: .now() + 120.0, execute: workItem)
641+
}
642+
}

0 commit comments

Comments
 (0)