diff --git a/hearo/HearoadWatch Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json b/hearo/HearoadWatch Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json
index 2698331..eb5a431 100644
--- a/hearo/HearoadWatch Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/hearo/HearoadWatch Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "Icon 오후 9.05.06.png",
+ "filename" : "Icon 오후 9.05.06.png",
"idiom" : "universal",
"platform" : "watchos",
"size" : "1024x1024"
diff --git a/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 1.svg b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 1.svg
new file mode 100644
index 0000000..5bc2eab
--- /dev/null
+++ b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 1.svg
@@ -0,0 +1,5 @@
+
diff --git a/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 2.svg b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 2.svg
new file mode 100644
index 0000000..5bc2eab
--- /dev/null
+++ b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution 2.svg
@@ -0,0 +1,5 @@
+
diff --git a/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution.svg b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution.svg
new file mode 100644
index 0000000..5bc2eab
--- /dev/null
+++ b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Caution.svg
@@ -0,0 +1,5 @@
+
diff --git a/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Contents.json b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Contents.json
new file mode 100644
index 0000000..26cab3d
--- /dev/null
+++ b/hearo/LiveActivity/Assets.xcassets/Caution.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "Caution.svg",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "Caution 1.svg",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "Caution 2.svg",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/hearo/LiveActivity/LiveActivityLiveActivity.swift b/hearo/LiveActivity/LiveActivityLiveActivity.swift
index 3576eb9..791230b 100644
--- a/hearo/LiveActivity/LiveActivityLiveActivity.swift
+++ b/hearo/LiveActivity/LiveActivityLiveActivity.swift
@@ -5,8 +5,6 @@
// Created by 김준수(엘빈) on 10/18/24.
//
-
-
import ActivityKit
import WidgetKit
import SwiftUI
@@ -14,29 +12,32 @@ import SwiftUI
// 라이브 액티비티 속성 정의
struct LiveActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
- // 현재 상태를 나타내는 속성을 정의 (예: 경고 여부)
- // 하지만 필요 없다면 이 속성을 추가적으로 활용할 수 있습니다.
+ // 현재 상태를 나타내는 속성을 정의
}
-
+
var name: String // 이름 속성만 유지
}
+
struct LiveActivityLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: LiveActivityAttributes.self) { context in
- // UI 구성
+ // Live Activity 구성
HStack {
- VStack {
- Text("소리 수집이 중지되었습니다.") // 변경된 메시지
- .font(.headline)
- .foregroundColor(.white)
+ VStack(alignment: .leading) {
+ Text("히어로드")
+ .font(.LiveActivitySub)
+ .foregroundColor(Color("MainFontColor"))
+ Text("소리수집이\n중지되었습니다.")
+ .font(.LiveActivityMain)
+ .foregroundColor(Color("MainFontColor"))
}
Spacer()
- Image(systemName: "exclamationmark.triangle") // 경고 아이콘
+ Image("Caution") // "Caution" 이미지를 왼쪽에 추가
.resizable()
.scaledToFit()
- .frame(width: 40, height: 40)
+ .frame(width: 91, height: 91)
.foregroundColor(.white)
}
.padding()
@@ -47,21 +48,42 @@ struct LiveActivityLiveActivity: Widget {
.activitySystemActionForegroundColor(Color.white)
} dynamicIsland: { context in
DynamicIsland {
- DynamicIslandExpandedRegion(.leading) {
- Image(systemName: "exclamationmark.triangle")
- }
DynamicIslandExpandedRegion(.center) {
- Text("소리 수집이 중지되었습니다.") // 동일한 메시지
- }
- DynamicIslandExpandedRegion(.trailing) {
- // 추가 아이콘이나 요소가 필요하다면 여기에 추가
+ HStack {
+ Image("Caution") // 아이콘
+ .resizable()
+ .scaledToFit()
+ .frame(width: 59, height: 59, alignment: .top)
+ .foregroundColor(.white)
+
+ Spacer() // 아이콘과 텍스트 사이 간격
+
+ VStack(alignment: .leading) { // 텍스트 영역
+ Text("히어로드")
+ .font(.LiveActivitySub)
+ .foregroundColor(Color("SubFontColor"))
+ Text("소리수집이 중지되었습니다.")
+ .font(.medium)
+ .foregroundColor(Color("MainFontColor"))
+ }
+ }
+ .padding() // 전체 패딩 추가
+ .frame(maxWidth: .infinity, maxHeight: 82) // HStack 최대 너비 설정
}
} compactLeading: {
- Image(systemName: "exclamationmark.triangle")
+ Image("Caution")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 30, height: 30)
} compactTrailing: {
- Text("수집 중지")
+ Text("수집중지")
+ .font(.DaynamicIsland)
+ .foregroundColor(Color("MainFontColor"))
} minimal: {
- Image(systemName: "exclamationmark.triangle")
+ Image("Caution")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 30, height: 30)
}
}
}
diff --git a/hearo/hearo.xcodeproj/project.pbxproj b/hearo/hearo.xcodeproj/project.pbxproj
index 4435e14..6ffb94e 100644
--- a/hearo/hearo.xcodeproj/project.pbxproj
+++ b/hearo/hearo.xcodeproj/project.pbxproj
@@ -45,6 +45,7 @@
1121777B2CC283BC000A146F /* LiveActivityLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1121777A2CC283BC000A146F /* LiveActivityLiveActivity.swift */; };
112177812CC283BD000A146F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 112177802CC283BD000A146F /* Assets.xcassets */; };
112177852CC283BD000A146F /* LiveActivityExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 112177712CC283BC000A146F /* LiveActivityExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ 11A2D0882CDE344500BF2BAF /* FontDesignSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D1B7572CDDD9D800BA2AF1 /* FontDesignSystem.swift */; };
64F73A252CBAC9F100D2A140 /* HornSoundDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F73A242CBAC9F100D2A140 /* HornSoundDetector.swift */; };
64F73A272CBAD1C000D2A140 /* SoundDetectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F73A262CBAD1C000D2A140 /* SoundDetectorViewModel.swift */; };
/* End PBXBuildFile section */
@@ -841,6 +842,7 @@
buildActionMask = 2147483647;
files = (
112177792CC283BC000A146F /* LiveActivityBundle.swift in Sources */,
+ 11A2D0882CDE344500BF2BAF /* FontDesignSystem.swift in Sources */,
1121777B2CC283BC000A146F /* LiveActivityLiveActivity.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1008,7 +1010,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"hearo/Preview Content\"";
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = hearo/Info.plist;
@@ -1042,7 +1044,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"hearo/Preview Content\"";
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = hearo/Info.plist;
@@ -1148,7 +1150,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"HearoadWatch Watch App/Preview Content\"";
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "HearoadWatch-Watch-App-Info.plist";
@@ -1179,7 +1181,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"HearoadWatch Watch App/Preview Content\"";
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "HearoadWatch-Watch-App-Info.plist";
@@ -1287,7 +1289,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LiveActivity/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
@@ -1315,7 +1317,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = J5N8Y9F8Z8;
+ DEVELOPMENT_TEAM = GT56H2MYWV;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LiveActivity/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LiveActivity;
diff --git a/hearo/hearo/Application/hearoApp.swift b/hearo/hearo/Application/hearoApp.swift
index 580551c..d310326 100644
--- a/hearo/hearo/Application/hearoApp.swift
+++ b/hearo/hearo/Application/hearoApp.swift
@@ -13,19 +13,28 @@ import WatchConnectivity
@main
struct hearoApp: App {
@StateObject var appRootManager = AppRootManager() // 앱 전역에서 사용되는 상태 관리
+ @Environment(\.scenePhase) private var scenePhase // 앱 상태 감지
var body: some Scene {
WindowGroup {
- // ContentView가 루트로 설정됨
- ZStack{
-
-
- Color("Background")
- .ignoresSafeArea(.all)
- ContentView(appRootManager: appRootManager)
+ ZStack {
+ Color("Background")
+ .ignoresSafeArea(.all)
+ ContentView(appRootManager: appRootManager)
+ }
+ .onChange(of: scenePhase) { newPhase in
+ handleScenePhaseChange(newPhase)
}
}
}
+
+ private func handleScenePhaseChange(_ newPhase: ScenePhase) {
+ if newPhase == .background && appRootManager.currentRoot == .working {
+ appRootManager.startLiveActivity(isWarning: false)
+ } else if newPhase == .inactive || newPhase == .active {
+ appRootManager.stopLiveActivity()
+ }
+ }
}
// 라이브 액티비티 속성 정의
@@ -44,8 +53,6 @@ final class AppRootManager: ObservableObject {
private var isWarning = false // isWarning 상태 저장
private var currentWarningState: Bool = false // 현재 isWarning 상태 저장
-
-
// 루트 뷰 상태를 나타내는 열거형
enum AppRoot {
case splash
@@ -62,9 +69,12 @@ final class AppRootManager: ObservableObject {
let hasSeenOnboarding = UserDefaults.standard.bool(forKey: "hasSeenOnboarding")
self.currentRoot = hasSeenOnboarding ? .home : .startOnboarding
}
-
+
// 라이브 액티비티 시작 메서드
func startLiveActivity(isWarning: Bool) {
+ // 항상 현재 `Live Activity` 상태를 확인하고 초기화
+ isActivityActive = Activity.activities.isEmpty == false
+
guard !isActivityActive else {
print("라이브 액티비티가 이미 활성화되어 있습니다.")
return
@@ -74,32 +84,30 @@ final class AppRootManager: ObservableObject {
print("라이브 액티비티가 지원되지 않거나 비활성화되었습니다.")
return
}
-
+
// attributes와 initialContentState를 선언
let attributes = LiveActivityAttributes(name: "주행")
let initialContentState = LiveActivityAttributes.ContentState(isWarning: isWarning)
- let content = ActivityContent(state: initialContentState, staleDate: nil)
+
+ let content = ActivityContent(state: initialContentState, staleDate: Date().addingTimeInterval(6)) // 전체 6초
do {
- // attributes와 content를 사용하여 라이브 액티비티 요청
let activity = try Activity.request(
attributes: attributes,
content: content
)
isActivityActive = true
- currentWarningState = isWarning // 현재 상태를 저장
+ currentWarningState = isWarning
print("라이브 액티비티가 시작되었습니다: \(activity.id)")
} catch {
print("라이브 액티비티 시작 실패: \(error)")
}
}
-
-
+
+
+ // 라이브 액티비티 종료 메서드
func stopLiveActivity() {
- let initialContentState = LiveActivityAttributes.ContentState(isWarning: isWarning)
- _ = ActivityContent(state: initialContentState, staleDate: nil)
-
guard isActivityActive else {
print("라이브 액티비티가 이미 중지 상태입니다.")
return
@@ -107,7 +115,7 @@ final class AppRootManager: ObservableObject {
Task {
for activity in Activity.activities {
- await activity.end(nil , dismissalPolicy: .immediate)
+ await activity.end(nil, dismissalPolicy: .immediate)
print("라이브 액티비티가 중지되었습니다: \(activity.id)")
}
@@ -115,49 +123,33 @@ final class AppRootManager: ObservableObject {
currentWarningState = false // 중지되었으므로 상태 리셋
}
}
-
+
// 라이브 액티비티 업데이트 메서드
- func updateLiveActivity(isWarning: Bool) {
- let initialContentState = LiveActivityAttributes.ContentState(isWarning: isWarning)
- let content = ActivityContent(state: initialContentState, staleDate: nil)
-
- guard isActivityActive else {
- print("활성화된 라이브 액티비티가 없어 업데이트할 수 없습니다.")
- return
- }
-
- // 같은 경고 상태로는 업데이트하지 않도록 체크
- guard isWarning != currentWarningState else {
- print("경고 상태가 이미 \(isWarning)로 설정되어 있습니다.")
- return
- }
- guard let activity = Activity.activities.first else {
- isActivityActive = false
- return
- }
-
- Task {
- _ = LiveActivityAttributes.ContentState(isWarning: isWarning)
- await activity.update(content) // `using` 레이블 제거
- print("라이브 액티비티 상태 업데이트: \(isWarning ? "경고" : "주행 중")")
- }
- }
-// func updateLiveActivity(iconName: String) {
-// guard let activity = activity else {
-// print("라이브 액티비티가 실행 중이지 않습니다.")
-// startLiveActivity(iconName: iconName)
-// return
-// }
-//
-// print("라이브 액티비티 업데이트 시도")
-// let state = DynamicAttributes.ContentState(remainingTime: remainingTime, iconName: iconName)
-// let content = ActivityContent(state: state, staleDate: Date().addingTimeInterval(3600))
-//
-// Task {
-// await activity.update(content)
-// print("라이브 액티비티 업데이트됨")
-// }
-// }
+ func updateLiveActivity(isWarning: Bool) {
+ let initialContentState = LiveActivityAttributes.ContentState(isWarning: isWarning)
+ let content = ActivityContent(state: initialContentState, staleDate: Date().addingTimeInterval(6)) // 전체 6초 유지
+
+ guard isActivityActive else {
+ print("활성화된 라이브 액티비티가 없어 업데이트할 수 없습니다.")
+ return
+ }
+
+ // 같은 경고 상태로는 업데이트하지 않도록 체크
+ guard isWarning != currentWarningState else {
+ print("경고 상태가 이미 \(isWarning)로 설정되어 있습니다.")
+ return
+ }
+ guard let activity = Activity.activities.first else {
+ isActivityActive = false
+ return
+ }
+
+ Task {
+ _ = LiveActivityAttributes.ContentState(isWarning: isWarning)
+ await activity.update(content)
+ print("라이브 액티비티 상태 업데이트: \(isWarning ? "경고" : "주행 중")")
+ }
+ }
}
// ContentView 정의 (AppRootManager 클래스 외부에 위치)
@@ -170,7 +162,7 @@ struct ContentView: View {
case .splash:
SplashView(appRootManager: appRootManager)
case .startOnboarding:
- StartOnboardingView(appRootManager: appRootManager)
+ StartOnboardingView(appRootManager: appRootManager)
case .onboarding:
OnboardingView(viewModel: OnboardingViewModel(appRootManager: appRootManager))
case .home:
@@ -185,4 +177,3 @@ struct ContentView: View {
}
}
}
-
diff --git a/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
index ac08590..e38e289 100644
--- a/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "Icon 오후 9.05.06.png",
+ "filename" : "Icon 오후 9.05.06.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
@@ -13,6 +13,7 @@
"value" : "dark"
}
],
+ "filename" : "Icon 오후 9.05.06 1.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
@@ -24,6 +25,7 @@
"value" : "tinted"
}
],
+ "filename" : "Icon 오후 9.05.06 2.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
diff --git "a/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 1.png" "b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 1.png"
new file mode 100644
index 0000000..a874d0e
Binary files /dev/null and "b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 1.png" differ
diff --git "a/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 2.png" "b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 2.png"
new file mode 100644
index 0000000..a874d0e
Binary files /dev/null and "b/hearo/hearo/Resources/Assets.xcassets/AppIcon.appiconset/Icon \354\230\244\355\233\204 9.05.06 2.png" differ
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 1.svg
new file mode 100644
index 0000000..aa479d3
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 1.svg
@@ -0,0 +1,18 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 2.svg
new file mode 100644
index 0000000..aa479d3
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Car 2.svg
@@ -0,0 +1,18 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Contents.json
index 0f2ca9d..c6e81ec 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Car.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "Car 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "Car 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 1.svg
new file mode 100644
index 0000000..5bc2eab
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 1.svg
@@ -0,0 +1,5 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 2.svg
new file mode 100644
index 0000000..5bc2eab
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Caution 2.svg
@@ -0,0 +1,5 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Contents.json
index f57f8bf..26cab3d 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Caution.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "Caution 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "Caution 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 1.svg
new file mode 100644
index 0000000..b735006
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 1.svg
@@ -0,0 +1,10 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 2.svg
new file mode 100644
index 0000000..b735006
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/CompletionCheck 2.svg
@@ -0,0 +1,10 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/Contents.json
index 8768ca8..6fbba65 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/CompletionCheck.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "CompletionCheck 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "CompletionCheck 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Contents.json
index 7d84448..7bf8ca9 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "Copyright 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "Copyright 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 1.svg
new file mode 100644
index 0000000..b712c6e
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 1.svg
@@ -0,0 +1,45 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 2.svg
new file mode 100644
index 0000000..b712c6e
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Copyright.imageset/Copyright 2.svg
@@ -0,0 +1,45 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/Contents.json
index bdcde5d..d03f45f 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "HearoadLetters 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "HearoadLetters 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 1.svg
new file mode 100644
index 0000000..f1fa768
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 1.svg
@@ -0,0 +1,9 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 2.svg
new file mode 100644
index 0000000..f1fa768
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/HearoadLetters.imageset/HearoadLetters 2.svg
@@ -0,0 +1,9 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Contents.json
index 5df36d0..b95e909 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Contents.json
@@ -1,15 +1,17 @@
{
"images" : [
{
- "filename" : "Icon 오후 9.05.06.png",
+ "filename" : "Icon 오후 9.05.06 1.png",
"idiom" : "universal",
"scale" : "1x"
},
{
+ "filename" : "Icon 오후 9.05.06.png",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "Icon 오후 9.05.06 2.png",
"idiom" : "universal",
"scale" : "3x"
}
diff --git "a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 1.png" "b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 1.png"
new file mode 100644
index 0000000..a874d0e
Binary files /dev/null and "b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 1.png" differ
diff --git "a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 2.png" "b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 2.png"
new file mode 100644
index 0000000..a874d0e
Binary files /dev/null and "b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/Icon.imageset/Icon \354\230\244\355\233\204 9.05.06 2.png" differ
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/Contents.json
index 82ef3b3..42a22c1 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "MainCircle 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "MainCircle 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 1.svg
new file mode 100644
index 0000000..a296ccc
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 1.svg
@@ -0,0 +1,37 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 2.svg
new file mode 100644
index 0000000..a296ccc
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/MainCircle.imageset/MainCircle 2.svg
@@ -0,0 +1,37 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/Contents.json
index 2194a37..fece7d9 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "OnboardingCircle 1.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "OnboardingCircle 2.svg",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 1.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 1.svg
new file mode 100644
index 0000000..b23a52e
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 1.svg
@@ -0,0 +1,42 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 2.svg b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 2.svg
new file mode 100644
index 0000000..b23a52e
--- /dev/null
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/OnboardingCircle.imageset/OnboardingCircle 2.svg
@@ -0,0 +1,42 @@
+
diff --git a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/StartButton.imageset/Contents.json b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/StartButton.imageset/Contents.json
index f5e64f7..4c2be32 100644
--- a/hearo/hearo/Resources/Assets.xcassets/SVGIcon/StartButton.imageset/Contents.json
+++ b/hearo/hearo/Resources/Assets.xcassets/SVGIcon/StartButton.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "시작하기.svg",
+ "filename" : "시작하기.svg",
"idiom" : "universal",
"scale" : "1x"
},
diff --git a/hearo/hearo/Resources/FontDesignSystem.swift b/hearo/hearo/Resources/FontDesignSystem.swift
index a5bbf26..2fc916b 100644
--- a/hearo/hearo/Resources/FontDesignSystem.swift
+++ b/hearo/hearo/Resources/FontDesignSystem.swift
@@ -12,4 +12,8 @@ extension Font {
static let light = Font.custom("Pretendard-Light", size: 18) // Light - title1
static let regular = Font.custom("Pretendard-Regular", size: 15) // Regular - title2
static let mainTitle = Font.custom("Pretendard-Medium", size: 24) // Medium
+ static let LiveActivityMain = Font.custom("Pretendard-Medium", size: 20)
+ static let LiveActivitySub = Font.custom("Pretendard-Light", size: 13)
+ static let DaynamicIsland = Font.custom("Pretendard-Medium", size: 8)
+
}
diff --git a/hearo/hearo/Sources/Helper/HornSoundDetector.swift b/hearo/hearo/Sources/Helper/HornSoundDetector.swift
index 088e993..65f681f 100644
--- a/hearo/hearo/Sources/Helper/HornSoundDetector.swift
+++ b/hearo/hearo/Sources/Helper/HornSoundDetector.swift
@@ -1,4 +1,3 @@
-
//
// HornSoundDetector.swift
// hearo
@@ -20,6 +19,16 @@ class HornSoundDetector: NSObject, ObservableObject {
private var inputNode: AVAudioInputNode!
private var soundClassifier: HornSoundClassifier_V11?
private var streamAnalyzer: SNAudioStreamAnalyzer?
+//fix 시작
+// @Published var isRecording = false
+// @Published var classificationResult = "녹음 시작 전"
+// @Published var detectedHornSound = false
+// @Published var topClassification: SNClassification? // 가장 높은 분류 저장
+// @Published var mlConfidences: [Double] = Array(repeating: 0.0, count: 4) // 각 채널의 신뢰도 배열
+// private var cancellables = Set()
+
+// override init() {
+//fix 끝
private var appRootManager: AppRootManager // appRootManager 속성 추가
@Published var isRecording = false
@@ -28,10 +37,16 @@ class HornSoundDetector: NSObject, ObservableObject {
init(appRootManager: AppRootManager) {
self.appRootManager = appRootManager
+
super.init()
setupAudioSession()
setupAudioEngine()
setupSoundClassifier()
+//fix
+// checkNotificationPermission()
+
+ // 앱이 백그라운드로 전환될 때 녹음을 중지하도록 옵저버 설정
+//fix
NotificationCenter.default.addObserver(self, selector: #selector(stopRecording), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
@@ -44,6 +59,13 @@ class HornSoundDetector: NSObject, ObservableObject {
print("오디오 세션 설정 실패: \(error)")
}
}
+ //fix
+// private func setupAudioEngine() {
+// audioEngine = AVAudioEngine()
+// inputNode = audioEngine.inputNode
+// }
+
+//fix
private func setupAudioEngine() {
audioEngine = AVAudioEngine()
@@ -63,18 +85,58 @@ class HornSoundDetector: NSObject, ObservableObject {
print("소리 분류기 생성 실패: \(error)")
}
}
+//fix
+
+// private func checkNotificationPermission() {
+// UNUserNotificationCenter.current().getNotificationSettings { settings in
+// switch settings.authorizationStatus {
+// case .notDetermined:
+// self.requestNotificationPermission()
+// case .denied:
+// print("알림 권한이 거부되었습니다. 설정에서 권한을 변경해주세요.")
+// case .authorized, .provisional, .ephemeral:
+// print("알림 권한이 허용되었습니다.")
+// @unknown default:
+// break
+// }
+// }
+// }
+
+// private func requestNotificationPermission() {
+// UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
+// if granted {
+// print("알림 권한이 허용되었습니다.")
+// } else if let error = error {
+// print("알림 권한 요청 중 오류 발생: \(error.localizedDescription)")
+// }
+// }
+// }
+
+//fix
+
func startRecording() {
guard !isRecording else {
print("녹음이 이미 시작된 상태입니다.")
return
}
-
+//fix
+
+// let format = inputNode.outputFormat(forBus: 0)
+// streamAnalyzer = SNAudioStreamAnalyzer(format: format)
+
+// guard let streamAnalyzer = streamAnalyzer,
+// let soundClassifier = soundClassifier else {
+// print("스트림 분석기 또는 소리 분류기 생성 실패")
+// return
+// }
+//fix
guard let streamAnalyzer = streamAnalyzer, let soundClassifier = soundClassifier else {
print("스트림 분석기 또는 소리 분류기 생성 실패")
return
}
+
do {
let request = try SNClassifySoundRequest(mlModel: soundClassifier.model)
try streamAnalyzer.add(request, withObserver: self)
@@ -82,12 +144,20 @@ class HornSoundDetector: NSObject, ObservableObject {
print("분류 요청 생성 실패: \(error)")
return
}
+// //fix
+
+// inputNode.installTap(onBus: 0, bufferSize: 8192, format: format) { [weak self] buffer, time in
+// self?.streamAnalyzer?.analyze(buffer, atAudioFramePosition: time.sampleTime)
+// }
+
+//fix
let format = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 8192, format: format) { [weak self] buffer, time in
self?.streamAnalyzer?.analyze(buffer, atAudioFramePosition: time.sampleTime)
}
+
audioEngine.prepare()
do {
try audioEngine.start()
@@ -112,7 +182,10 @@ class HornSoundDetector: NSObject, ObservableObject {
print("오디오 엔진 중지됨")
}
+
func sendNotification(title: String, body: String) {
+ print("알림 발송 시도")
+
let content = UNMutableNotificationContent()
content.title = title
content.body = body
@@ -133,6 +206,27 @@ extension HornSoundDetector: SNResultsObserving {
func request(_ request: SNRequest, didProduce result: SNResult) {
guard let result = result as? SNClassificationResult else { return }
+//fix
+// let topClassifications = result.classifications.prefix(3)
+
+// DispatchQueue.main.async {
+// // 첫 번째 분류를 가장 신뢰도 높은 것으로 설정
+// if let topClassification = topClassifications.first(where: { classification in
+// return classification.identifier == "Bicyclebell" || classification.identifier == "Carhorn" || classification.identifier == "Siren"
+// }) {
+// self.topClassification = topClassification // 가장 높은 분류 저장
+// self.classificationResult = topClassification.identifier // 소리 종류만 저장
+// }
+
+// for (index, classification) in topClassifications.enumerated() {
+// if classification.identifier == "Bicyclebell" || classification.identifier == "Carhorn" || classification.identifier == "Siren" {
+// // 경적 및 사이렌 소리 감지
+// if classification.confidence >= 1.0 {
+// self.mlConfidences[index] = classification.confidence
+// // 원하는 로직을 추가하세요
+// }
+// }
+//fix
DispatchQueue.main.async {
if let topClassification = result.classifications.first, topClassification.confidence >= 1.0 {
let isRelevantSound = ["Bicyclebell", "Carhorn", "Siren"].contains(topClassification.identifier)
@@ -144,6 +238,7 @@ extension HornSoundDetector: SNResultsObserving {
}
} else {
print("신뢰도 부족 또는 관련 없는 소리 감지됨")
+
}
}
}
diff --git a/hearo/hearo/Sources/Helper/SoundDetectorViewModel.swift b/hearo/hearo/Sources/Helper/SoundDetectorViewModel.swift
index e643a22..0a77a5e 100644
--- a/hearo/hearo/Sources/Helper/SoundDetectorViewModel.swift
+++ b/hearo/hearo/Sources/Helper/SoundDetectorViewModel.swift
@@ -10,9 +10,17 @@ import WatchConnectivity
class SoundDetectorViewModel: NSObject, ObservableObject, WCSessionDelegate {
@Published var isRecording = false
+//fix
+// @Published var classificationResults: [String] = Array(repeating: "녹음 시작 전", count: 4)
+// @Published var detectedHornSounds: [Bool] = Array(repeating: false, count: 4)
+
+// private var soundDetectors: [HornSoundDetector] = []
+// private var mlConfidences: [Double] = Array(repeating: 0.0, count: 4)
+//fix
@Published var classificationResult: String = "녹음 시작 전"
private var soundDetector: HornSoundDetector
+
private var cancellables = Set()
private var appRootManager: AppRootManager
private var isActivityActive = false
@@ -30,15 +38,82 @@ class SoundDetectorViewModel: NSObject, ObservableObject, WCSessionDelegate {
WCSession.default.activate()
}
+//fix
+// for _ in 0..<4 {
+// let soundDetector = HornSoundDetector()
+// soundDetectors.append(soundDetector)
+// }
+//fix
// for _ in 0..<4 {
// let soundDetector = HornSoundDetector()
// soundDetectors.append(soundDetector)
// }
+
setupBindings()
}
private func setupBindings() {
+//fix
+// for (index, soundDetector) in soundDetectors.enumerated() {
+// soundDetector.$isRecording
+// .assign(to: \.isRecording, on: self)
+// .store(in: &cancellables)
+
+// soundDetector.$classificationResult
+// .sink { [weak self] result in
+// self?.classificationResults[index] = result
+// }
+// .store(in: &cancellables)
+
+// soundDetector.$detectedHornSound
+// .sink { [weak self] detected in
+// self?.detectedHornSounds[index] = detected
+// }
+// .store(in: &cancellables)
+
+// soundDetector.$topClassification
+// .sink { [weak self] topClassification in
+// guard let self = self else { return }
+// if let classification = topClassification {
+// self.mlConfidences[index] = classification.confidence
+// self.checkAllConfidences()
+// }
+// }
+// .store(in: &cancellables)
+// }
+// }
+
+// private func checkAllConfidences() {
+// // 모든 마이크의 신뢰도가 0.99 이상인지 확인
+// if mlConfidences.allSatisfy({ $0 >= 0.99 }) {
+// DispatchQueue.main.async {
+// self.appRootManager.currentRoot = .warning
+// self.sendWarningToWatch() // 애플워치에 경고 전송
+// self.updateApplicationContext() // 애플워치에 데이터 전송
+// }
+// }
+// }
+
+// private func getHighestConfidenceSound() -> String? {
+// if let highestConfidenceIndex = mlConfidences.enumerated().max(by: { $0.element < $1.element })?.offset,
+// highestConfidenceIndex < classificationResults.count {
+// return classificationResults[highestConfidenceIndex]
+// }
+// return nil
+// }
+
+// private func updateApplicationContext() {
+// do {
+// if let highestConfidenceSound = getHighestConfidenceSound() {
+// let context = ["highestConfidenceSound": highestConfidenceSound]
+// try WCSession.default.updateApplicationContext(context)
+// print("applicationContext 데이터 전송 성공: \(context)")
+// }
+// } catch {
+// print("applicationContext 데이터 전송 실패: \(error.localizedDescription)")
+// }
+//fix
// for (index, soundDetector) in soundDetectors.enumerated() {
// soundDetector.$isRecording
@@ -116,6 +191,40 @@ class SoundDetectorViewModel: NSObject, ObservableObject, WCSessionDelegate {
print("애플워치가 연결되지 않음")
return
}
+//fix
+
+
+// if let highestConfidenceSound = getHighestConfidenceSound() {
+
+// let message = ["alert": highestConfidenceSound]
+
+// WCSession.default.sendMessage(message, replyHandler: nil) { error in
+// print("애플워치로 경고 메시지 전송 오류: \(error.localizedDescription)")
+// }
+// } else {
+// print("경고를 보낼 신뢰도 높은 소리가 없음")
+// }
+// }
+
+// func toggleRecording(start: Bool) {
+// for detector in soundDetectors {
+// if start {
+// detector.startRecording()
+// } else {
+// detector.stopRecording()
+// }
+// }
+// }
+
+// func startRecording() {
+// toggleRecording(start: true)
+// }
+
+// func stopRecording() {
+// toggleRecording(start: false)
+// }
+
+//fix
@@ -157,6 +266,7 @@ class SoundDetectorViewModel: NSObject, ObservableObject, WCSessionDelegate {
//
// }
//
+
// 필수 WCSessionDelegate 메서드 구현
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
print("MLWCSession 활성화 완료. 상태: \(activationState)")
diff --git a/hearo/hearo/Sources/Presentations/Home/View/HomeView.swift b/hearo/hearo/Sources/Presentations/Home/View/HomeView.swift
index 60c2970..6b6ec94 100644
--- a/hearo/hearo/Sources/Presentations/Home/View/HomeView.swift
+++ b/hearo/hearo/Sources/Presentations/Home/View/HomeView.swift
@@ -145,7 +145,7 @@ struct HomeView: View {
if startLottieAnimation {
LottieView(animationName: "start_view", animationScale: 1)
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
- .offset(y: targetOffset - UIScreen.main.bounds.height / 57)
+ .offset(y: 274)
.edgesIgnoringSafeArea(.all)
}
diff --git a/hearo/hearo/Sources/Presentations/Working/View/WorkingView.swift b/hearo/hearo/Sources/Presentations/Working/View/WorkingView.swift
index ea45dc7..f559d4d 100644
--- a/hearo/hearo/Sources/Presentations/Working/View/WorkingView.swift
+++ b/hearo/hearo/Sources/Presentations/Working/View/WorkingView.swift
@@ -28,7 +28,7 @@ struct WorkingView: View {
LottieView(animationName: "sound_collection", animationScale: 1)
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
// .offset(y: targetOffset - UIScreen.main.bounds.height / 4)
- .offset(x: -3,y: 60)
+ .offset(x: -1.4 ,y: 60)
.edgesIgnoringSafeArea(.all)
diff --git a/hearo/hearo/Sources/Presentations/Working/ViewModel/WorkingViewModel.swift b/hearo/hearo/Sources/Presentations/Working/ViewModel/WorkingViewModel.swift
index 1daa172..3b1ea21 100644
--- a/hearo/hearo/Sources/Presentations/Working/ViewModel/WorkingViewModel.swift
+++ b/hearo/hearo/Sources/Presentations/Working/ViewModel/WorkingViewModel.swift
@@ -8,8 +8,11 @@ import Foundation
import Combine
import SwiftUI
import AVFoundation
+
+
//import AudioToolbox
+
class WorkingViewModel: ObservableObject {
@Published var appRootManager: AppRootManager
@Published var soundDetectorViewModel: SoundDetectorViewModel
@@ -17,10 +20,15 @@ class WorkingViewModel: ObservableObject {
private var cancellables = Set() // Combine 구독을 저장하는 변수 추가
private var hornSoundDetector: HornSoundDetector // HornSoundDetector 사용
-
init(appRootManager: AppRootManager) {
self.appRootManager = appRootManager
self.soundDetectorViewModel = SoundDetectorViewModel(appRootManager: appRootManager)
+//fix
+// configureAudioSession() // AVAudioSession 설정
+// }
+//fix
+ // 오디오 세션 설정
+
self.hornSoundDetector = HornSoundDetector(appRootManager: appRootManager)
// AVAudioSession 설정
@@ -29,6 +37,7 @@ class WorkingViewModel: ObservableObject {
observeSoundDetection()
}
+
func configureAudioSession() {
do {
let audioSession = AVAudioSession.sharedInstance()
@@ -39,6 +48,15 @@ class WorkingViewModel: ObservableObject {
print("오디오 세션 설정 중 오류 발생: \(error.localizedDescription)")
}
}
+//fix
+ // 모든 채널의 분류 결과를 출력
+// var classificationResult: String {
+// var results = ""
+// for (index, result) in soundDetectorViewModel.classificationResults.enumerated() {
+// results += "채널 \(index + 1): \(result)\n"
+// }
+// return results
+//fix
private func observeSoundDetection() {
soundDetectorViewModel.$classificationResult
@@ -51,34 +69,54 @@ class WorkingViewModel: ObservableObject {
}
}
.store(in: &cancellables)
+
}
+ // 녹음 시작
func startRecording() {
guard !isRecording else {
print("녹음이 이미 진행 중입니다.")
return
}
+//fix
+// isRecording = true
+//fix
print("WorkingViewModel: startRecording() 호출됨")
hornSoundDetector.startRecording() // HornSoundDetector에서 처리
print("WorkingViewModel: 녹음 시작 완료")
- appRootManager.startLiveActivity(isWarning: false)
+ appRootManager.startLiveActivity(isWarning: false) // 녹음 시작 시 라이브 액티비티 활성화
}
+ // 녹음 중지
func stopRecording() {
guard isRecording else {
print("녹음이 이미 중지된 상태입니다.")
return
}
+//fix
+// isRecording = false
+//fix
print("WorkingViewModel: stopRecording() 호출됨")
hornSoundDetector.stopRecording() // HornSoundDetector에서 처리
print("녹음 중지 완료")
-
- appRootManager.stopLiveActivity()
+
+
+ appRootManager.stopLiveActivity() // 녹음 중지 시 라이브 액티비티 비활성화
+
}
+ // 녹음 완료 및 종료 화면으로 이동
func finishRecording() {
+ stopRecording() // 녹음 중지 메서드 호출
triggerErrorHaptic()
- appRootManager.currentRoot = .finish
+ appRootManager.currentRoot = .finish // 종료 화면으로 전환
}
+
+
+ // 햅틱 피드백 트리거
+ private func triggerErrorHaptic() {
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
+ }
+
}