Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6da23eb
refactor(app): 문법 교정 테스트 목적
Kimyonhae Jun 26, 2026
c2b411f
refactor(presentation,app): 의존성 추가 및 UI 수정
Kimyonhae Jun 26, 2026
0bc6b74
feat(data): 문법 교정 메모리 최적화
Kimyonhae Jun 26, 2026
bfd9cd0
feat(data): 문법 교정 구현체 추가 및 적용
Kimyonhae Jun 26, 2026
e6cf0c7
refactor(data): Gemma4 가중치 불확실성 보안 검증
Kimyonhae Jun 26, 2026
f81a6e5
refactor(domain): 의도되지 않은 버그 수정
Kimyonhae Jun 26, 2026
6edc085
refactor(all): Presentation 뷰에 기능 적용
Kimyonhae Jun 26, 2026
e959448
refactor(data): 문법 교정 메모리 최적화
Kimyonhae Jun 26, 2026
9b383ce
refactor(domain): VoiceNote 분석 직렬 대기열 도입 및 OOM 방지
Kimyonhae Jun 27, 2026
344efe2
refactor: swiftformat 스타일 적용
Kimyonhae Jun 27, 2026
9990a0b
refactor(presentation): Preview테스트 추가된 함수 작성
Kimyonhae Jun 27, 2026
e7f9357
feat(widget): LiveActivity 초기설정
Kimyonhae Jun 27, 2026
4c2cd41
refactor(domain): 램 사양 확인 버그 수정
Kimyonhae Jun 28, 2026
4c41560
feat(core): Process간 Notification 헬퍼 작성
Kimyonhae Jun 28, 2026
edec5cc
fix(widget): 라이브 액티비티 레이아웃 흔들림 및 다이내믹 아일랜드 늘어남 현상수정
Kimyonhae Jun 28, 2026
eb3f672
refactor(presentation): foreground전환 UIView.anitme살리기
Kimyonhae Jun 30, 2026
a340306
refactor(data): 문법 검사 순차 검사 최적화
Kimyonhae Jun 30, 2026
fc7d94c
refactor: 문법 교정 프롬프트 배칭 최적화 및 디버그 시드 데이터 수정
Kimyonhae Jun 30, 2026
fc10ba8
refactor: swiftforamt 스타일 정리
Kimyonhae Jun 30, 2026
951d16e
ci: 위젯 타겟 코드사인 설정 및 테스트 빌드 에러 수정
Kimyonhae Jun 30, 2026
3f7873c
refactor(widgetTest): testable 코드 제거
Kimyonhae Jun 30, 2026
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
6 changes: 5 additions & 1 deletion App/Sources/AppDIContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public final class AppDIContainer {
private lazy var mlxSummaryRepository = DefaultMLXSummaryRepository(
provider: mlxProvider
)
private lazy var mlxGrammarRepository = DefaultMLXGrammarRepository(
provider: mlxProvider
)
private lazy var whisperProvider = WhisperKitProvider(
storageService: storageService,
languageRepository: languageRepository
Expand All @@ -55,7 +58,8 @@ public final class AppDIContainer {
voiceNoteRepository: voiceNoteRepository,
sttRepository: sttWhisperRepository,
summaryRepository: mlxSummaryRepository,
languageRepository: languageRepository
languageRepository: languageRepository,
grammarRepository: mlxGrammarRepository
)

/// UseCase
Expand Down
13 changes: 13 additions & 0 deletions App/Sources/AppIntentsRegistry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import AppIntents
import Presentation

/// 메인 앱에서 Presentation 프레임워크의 AppIntent(LiveActivityIntent)를
/// 시스템이 인식할 수 있도록 등록합니다.
///
/// LiveActivityIntent는 메인 앱 프로세스에서 실행되므로,
/// 앱 타겟에서도 프레임워크의 Intent 메타데이터를 참조해야 합니다.
struct AppIntentsRegistry: AppIntentsPackage {
static var includedPackages: [any AppIntentsPackage.Type] {
[PresentationAppIntents.self]
}
}
44 changes: 31 additions & 13 deletions App/Sources/Debug/DebugSeeder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@
let voiceNoteRepository: any VoiceNoteRepository

func seedIfNeeded() {
let defaults = UserDefaults.standard
guard !defaults.bool(forKey: Self.didSeedKey) else {
AppLogger.debug("시드 데이터가 이미 존재합니다. 스킵.")
return
}

do {
let folders = try folderRepository.fetchAll()
guard folders.contains(where: { $0.kind == .default }) else {
AppLogger.debug("기본 폴더 미존재. 온보딩 이후 다시 시도합니다.")
return
}

// 디버그 빌드 시 매번 실행하여 최신 시드 데이터를 갱신합니다.
// 중복 및 이전 시드를 방지하기 위해 기존 시드 폴더를 먼저 삭제합니다 (Core Data cascade 삭제됨).
let seedFolderNames = ["업무", "개인", "학습", "회의록"]
for folder in folders {
if seedFolderNames.contains(folder.name) {
try folderRepository.delete(id: folder.id)
}
}

try performSeed()
defaults.set(true, forKey: Self.didSeedKey)
AppLogger.info("시드 데이터 생성 완료")
AppLogger.info("시드 데이터 초기화 및 재설정 완료")
} catch {
AppLogger.error("시드 데이터 생성 실패: \(error)")
AppLogger.error("시드 데이터 초기화 실패: \(error)")
}
}

Expand Down Expand Up @@ -236,6 +239,15 @@
summaryLines: [],
keywords: ["장애", "인시던트", "포스트모템"],
analysisState: .transcriptionFailed
),
Spec(
folderID: personalFolder.id,
title: "일정 및 버그 관련 푸념 메모 (문법 교정 테스트용)",
createdAt: now.addingTimeInterval(-h * 2),
texts: SeedContent.grammarCheckTest,
summaryLines: [],
keywords: [],
analysisState: .transcribed
)
]

Expand All @@ -245,7 +257,9 @@
}

private func createSeededNote(spec: Spec) throws {
let sections = SeedContent.buildSections(texts: spec.texts)
let sections = spec.title.contains("문법")
? SeedContent.buildLongSections(texts: spec.texts, totalDuration: 3600)
: SeedContent.buildSections(texts: spec.texts)
let duration = (sections.last?.timestamp ?? 0) + 3.0
let audioPath = try makeSilentAudioFile(duration: max(duration, 2.5))
let record = VoiceRecord(
Expand Down Expand Up @@ -288,14 +302,18 @@

private func shouldIncludeTranscript(for state: AnalysisState) -> Bool {
switch state {
case .pending, .transcribing, .transcriptionFailed:
case .pending, .transcribing, .transcriptionFailed, .waiting:
return false
case .transcribed, .summarizing, .regenerating, .completed, .summarizationFailed:
case .transcribed, .summarizing, .regenerating, .completed, .summarizationFailed, .grammarCheckFailed,
.grammarChecked, .grammarChecking:
return true
}
}

private func makeSilentAudioFile(duration: Double) throws -> String {
// 디버그용 무음 파일이므로 실제 파일 길이는 최대 5초로 제한하여
// 메인 스레드 병목 및 과도한 메모리/디스크 사용을 방지합니다.
let physicalDuration = min(duration, 5.0)
let directory = "VoiceRecords"
let fileName = "seed-\(UUID().uuidString).m4a"
let docURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
Expand All @@ -318,7 +336,7 @@
commonFormat: .pcmFormatFloat32,
interleaved: false
)
let frameCount = AVAudioFrameCount(file.processingFormat.sampleRate * duration)
let frameCount = AVAudioFrameCount(file.processingFormat.sampleRate * physicalDuration)
guard let buffer = AVAudioPCMBuffer(
pcmFormat: file.processingFormat,
frameCapacity: frameCount
Expand Down
Loading
Loading