Repository navigation
feat: 온보딩 구현 - #6
Conversation
- 확인이 필요한 스크린샷 알림 컴포넌트 - 스크린샷 처리 완료 알림 컴포넌트
There was a problem hiding this comment.
Pull request overview
Implements a new multi-step onboarding flow (Landing → policy → login(mock) → permission guidance → range select → cleanup start → home) and introduces an OCR cleanup pipeline backed by WorkManager + Room, alongside several new reusable UI components and theming updates.
Changes:
- Added new onboarding screens/flow logic with image-permission handling and progress UI.
- Implemented OCR job execution + persistence (WorkManager worker, Room DB/DAO/repository) and surfaced latest job progress on Home.
- Introduced/updated design components (RecapButton, bottom sheets, home cards) and added a Developer “Component Garden” screen.
Reviewed changes
Copilot reviewed 63 out of 63 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| gradle/libs.versions.toml | Adds version/catalog entries for Room/Work/AndroidX Hilt and material icons. |
| app/src/main/res/values/strings.xml | Adds onboarding/home/component-garden/bottom-sheet strings and updates range count formats. |
| app/src/main/res/drawable/ic_check_24.xml | Adds a check icon used for completed OCR UI. |
| app/src/main/res/drawable/bid_landscape_24px.xml | Adds a vector icon used in onboarding permission UI. |
| app/src/main/java/com/chalkak/recap/RecapApplication.kt | Integrates WorkManager Configuration.Provider with Hilt WorkerFactory. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingStartScreen.kt | Removes old onboarding start screen. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingPermissionGuideScreen.kt | Updates permission guide UI to use RecapButton + previews. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingLandingScreen.kt | Adds new onboarding landing screen. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingImagePolicyScreen.kt | Adds onboarding image policy step UI. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingFirstCleanupScreen.kt | Adds first-cleanup screen with permission bottom sheet logic. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingCleanupStartScreen.kt | Adds cleanup start/progress UI tied to OCR job progress. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingCleanupRangeScreen.kt | Enhances range selection with dynamic counts, permission gating, and previews. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/screen/OnboardingAuthScreen.kt | Refactors onboarding auth/login UI into a new login screen layout. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/OnboardingViewModel.kt | Migrates onboarding VM to Hilt + connects to OCR repository & permission/range count logic. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/OnboardingScreen.kt | Reworks onboarding step routing and adds SnackbarHost support + previews. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/OnboardingRoute.kt | Wires permission request/settings intents and onboarding completion behavior. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/OnboardingPreviews.kt | Adds shared preview annotations/container for onboarding screens. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/OnboardingContract.kt | Updates onboarding state/actions/steps and connects cleanup range to OCR ranges. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/OnboardingTopBar.kt | Adds a new onboarding top bar with back button + progress rendering. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/OnboardingGuideComponents.kt | Adds step header, bullets, and permission icon tile components. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/OnboardingComponents.kt | Removes legacy onboarding component implementations. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/OnboardingComponentPreviews.kt | Adds preview scaffolding for onboarding components. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/OnboardingBrandComponents.kt | Adds brand/illustration composables used in onboarding screens. |
| app/src/main/java/com/chalkak/recap/feature/onboarding/component/CleanupRangeOptionCard.kt | Extracts cleanup range option card into its own component file. |
| app/src/main/java/com/chalkak/recap/feature/mypage/MyPageScreen.kt | Minor parameter ordering cleanup. |
| app/src/main/java/com/chalkak/recap/feature/mypage/MyPageContract.kt | Switches @StringRes annotations to @get:StringRes. |
| app/src/main/java/com/chalkak/recap/feature/home/HomeViewModel.kt | Adds Hilt-backed VM exposing latest OCR job as UI state. |
| app/src/main/java/com/chalkak/recap/feature/home/HomeScreen.kt | Adds OCR progress card + raw result list UI on Home. |
| app/src/main/java/com/chalkak/recap/feature/home/HomeRoute.kt | Adds Home route wiring with Hilt VM. |
| app/src/main/java/com/chalkak/recap/feature/home/HomeContract.kt | Extends Home UI state to include latest OCR job. |
| app/src/main/java/com/chalkak/recap/feature/developer/DeveloperRoute.kt | Adds navigation destination for Component Garden. |
| app/src/main/java/com/chalkak/recap/feature/developer/DeveloperOptionsScreen.kt | Adds new developer option for Component Garden. |
| app/src/main/java/com/chalkak/recap/feature/developer/ComponentGardenScreen.kt | Adds a screen to showcase cards/buttons/bottom sheets. |
| app/src/main/java/com/chalkak/recap/feature/demo/RecentScreenshotsRow.kt | Updates previews to use toUri(). |
| app/src/main/java/com/chalkak/recap/feature/demo/DemoViewModel.kt | Migrates demo VM to Hilt and reuses LocalScreenshotDataSource for permission/query. |
| app/src/main/java/com/chalkak/recap/feature/demo/DemoScreen.kt | Switches demo screen to use hiltViewModel() and updates previews. |
| app/src/main/java/com/chalkak/recap/feature/demo/DemoContract.kt | Switches @StringRes annotations to @get:StringRes. |
| app/src/main/java/com/chalkak/recap/feature/demo/DemoContent.kt | Minor parameter ordering cleanup + updates previews to toUri(). |
| app/src/main/java/com/chalkak/recap/feature/collection/CollectionScreen.kt | Minor parameter ordering cleanup. |
| app/src/main/java/com/chalkak/recap/feature/collection/CollectionContract.kt | Switches @StringRes annotations to @get:StringRes. |
| app/src/main/java/com/chalkak/recap/core/model/OcrModels.kt | Adds domain models for OCR jobs/ranges/results. |
| app/src/main/java/com/chalkak/recap/core/model/LocalImage.kt | Adds a model for MediaStore images. |
| app/src/main/java/com/chalkak/recap/core/model/ImageAccessLevel.kt | Adds image access level enum (Full/Selected/Denied). |
| app/src/main/java/com/chalkak/recap/core/design/theme/Theme.kt | Updates app color scheme and disables dynamic color by default. |
| app/src/main/java/com/chalkak/recap/core/design/theme/Color.kt | Defines new Recap color palette constants. |
| app/src/main/java/com/chalkak/recap/core/design/component/ReviewRequiredScreenshotCard.kt | Adds a new home card component. |
| app/src/main/java/com/chalkak/recap/core/design/component/RecapPlaceholderScreen.kt | Uses RecapButton for placeholder screen actions. |
| app/src/main/java/com/chalkak/recap/core/design/component/RecapButton.kt | Adds RecapButton design-system component with sizing, icons, shadows, etc. |
| app/src/main/java/com/chalkak/recap/core/design/component/PhotoAccessPermissionBottomSheet.kt | Adds permission request bottom sheet component. |
| app/src/main/java/com/chalkak/recap/core/design/component/OrganizedCaptureCard.kt | Adds a “organized captures” home card component. |
| app/src/main/java/com/chalkak/recap/core/design/component/KakaoLoginButton.kt | Removes legacy Kakao login button (replaced by RecapButton usage). |
| app/src/main/java/com/chalkak/recap/core/design/component/ImageLoadFailureBottomSheet.kt | Adds image-load failure bottom sheet component. |
| app/src/main/java/com/chalkak/recap/core/data/WorkManagerModule.kt | Provides WorkManager via Hilt. |
| app/src/main/java/com/chalkak/recap/core/data/RecapDatabase.kt | Adds Room database definition for OCR entities. |
| app/src/main/java/com/chalkak/recap/core/data/ocr/OcrWorker.kt | Adds WorkManager worker that runs ML Kit OCR and persists results. |
| app/src/main/java/com/chalkak/recap/core/data/ocr/OcrRepository.kt | Adds repository coordinating permissions, counts, DB observation, and OCR work enqueueing. |
| app/src/main/java/com/chalkak/recap/core/data/ocr/OcrEntities.kt | Adds Room entities + domain mapping helpers. |
| app/src/main/java/com/chalkak/recap/core/data/ocr/OcrDao.kt | Adds DAO for OCR jobs/results and progress updates. |
| app/src/main/java/com/chalkak/recap/core/data/LocalScreenshotDataSource.kt | Adds MediaStore-based screenshot query + permission utilities. |
| app/src/main/java/com/chalkak/recap/core/data/DatabaseModule.kt | Provides Room database/DAO via Hilt. |
| app/src/main/java/com/chalkak/recap/app/RecapNavHost.kt | Switches Home destination to HomeRoute. |
| app/src/main/AndroidManifest.xml | Removes default WorkManager initializer via manifest merge rules. |
| app/build.gradle.kts | Adds dependencies for Room, WorkManager, AndroidX Hilt, and material icons extended + KSP processors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import android.app.Application | ||
| import androidx.hilt.work.HiltWorkerFactory | ||
| import androidx.work.Configuration | ||
| import com.google.android.datatransport.BuildConfig |
| fun currentImageAccessLevel(): ImageAccessLevel { | ||
| return when { | ||
| Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && | ||
| context.hasPermission(Manifest.permission.READ_MEDIA_IMAGES) -> ImageAccessLevel.Full | ||
|
|
||
| Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && | ||
| context.hasPermission(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) -> ImageAccessLevel.Selected | ||
|
|
||
| Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU && | ||
| context.hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) -> ImageAccessLevel.Full | ||
|
|
||
| else -> ImageAccessLevel.Denied | ||
| } | ||
| } |
| <string name="onboarding_start_button">시작하기</string> | ||
| <string name="component_garden_title">컴포넌트 가든</string> | ||
| <string name="component_garden_home_cards_section_title">홈 카드</string> | ||
| <string name="component_garden_ui_components_section_title"> 컴포넌트</string> |
| viewModelScope.launch { | ||
| val counts = CleanupRange.entries.associateWith { range -> | ||
| ocrRepository.countScreenshots(range.ocrRange) | ||
| } | ||
| _uiState.update { current -> |
| private fun startOcrAndMoveToCleanup() { | ||
| val selectedRange = _uiState.value.selectedRange | ||
| if (!_uiState.value.canConfirmRange) { | ||
| _uiState.update { current -> | ||
| current.copy(errorMessage = "cleanup_range_unavailable") | ||
| } | ||
| return | ||
| } | ||
|
|
||
| _uiState.update { current -> current.copy(activeOcrJob = null) } | ||
| moveTo(OnboardingStep.CleanupStart) | ||
| viewModelScope.launch { | ||
| _uiState.update { current -> current.copy(isLoading = true, errorMessage = null) } | ||
| runCatching { | ||
| ocrRepository.startOcr(selectedRange.ocrRange) | ||
| }.onFailure { | ||
| _uiState.update { current -> | ||
| current.copy(errorMessage = "ocr_start_failed") | ||
| } |
3de8f34 to
e0655a5
Compare
| override fun onCreate() { | ||
| super.onCreate() | ||
|
|
||
| if (BuildConfig.DEBUG) { | ||
| Timber.plant(Timber.DebugTree()) | ||
| } | ||
| } |
| viewModelScope.launch { | ||
| val counts = CleanupRange.entries.associateWith { range -> | ||
| ocrRepository.countScreenshots(range.ocrRange) | ||
| } | ||
| _uiState.update { current -> | ||
| current.copy( | ||
| rangeCounts = counts, | ||
| isRangeCountLoading = false, | ||
| errorMessage = null, | ||
| ) | ||
| } | ||
| } |
| private fun startOcrAndMoveToCleanup() { | ||
| val selectedRange = _uiState.value.selectedRange | ||
| if (!_uiState.value.canConfirmRange) { | ||
| _uiState.update { current -> | ||
| current.copy(errorMessage = "cleanup_range_unavailable") | ||
| } | ||
| return | ||
| } | ||
|
|
||
| _uiState.update { current -> current.copy(activeOcrJob = null) } | ||
| moveTo(OnboardingStep.CleanupStart) | ||
| viewModelScope.launch { | ||
| _uiState.update { current -> current.copy(isLoading = true, errorMessage = null) } | ||
| runCatching { | ||
| ocrRepository.startOcr(selectedRange.ocrRange) | ||
| }.onFailure { | ||
| _uiState.update { current -> | ||
| current.copy(errorMessage = "ocr_start_failed") | ||
| } |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e0655a5b9a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| val screenshotRelativePaths = listOf( | ||
| "DCIM/Screenshots/", | ||
| ) |
There was a problem hiding this comment.
Include non-DCIM screenshot folders
On devices that store screenshots in Pictures/Screenshots/ instead of DCIM/Screenshots/, this exact RELATIVE_PATH filter makes countScreenshots() and queryScreenshots() return empty lists even after full photo permission. That leaves onboarding stuck on the empty/disabled cleanup path for users who do have screenshots, so include the other common screenshot location or detect screenshot buckets more broadly.
Useful? React with 👍 / 👎.
| text = if (job.isCompleted) { | ||
| stringResource(R.string.home_ocr_complete_title) | ||
| } else { | ||
| stringResource(R.string.home_ocr_running_title) | ||
| }, |
There was a problem hiding this comment.
Distinguish failed OCR jobs from running ones
OcrWorker persists Failed and Cancelled statuses, but this branch renders every non-completed job with the running title. When OCR fails, for example because ML Kit or URI loading throws, Home keeps showing an analysis-running progress card even though the work is finished, leaving users with stale status and no error/retry path.
Useful? React with 👍 / 👎.
Summary
Notes