feat(e11): manual hide controls — long-press to hide repos#587
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a "hide repository" feature: DB v17 + migration and DAO/entity, domain model & repo interface, repository impl + DI, Compose long-press + hide sheet, Home/Search wiring and filtering, navigation/screen, and localized strings/whatsnew. ChangesHide Repository Feature
Sequence Diagram (high-level hide flow): sequenceDiagram
participant UI as RepositoryCard(UI)
participant VM as HomeViewModel / SearchViewModel
participant Repo as HiddenReposRepository
participant DB as Room/HiddenRepoDao
UI->>VM: OnHideRepository(repo)
VM->>Repo: hide(repoId, repoName, repoOwner, repoOwnerAvatarUrl)
Repo->>DB: insert HiddenRepoEntity(...)
DB-->>Repo: confirm insert
Repo-->>VM: Flow update (hidden repo ids)
VM-->>UI: state.hiddenRepoIds updated (UI recomputes visible repos)
🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.kt (1)
14-69: 💤 Low valueConsider extracting common ElevatedCard properties to reduce duplication.
The three branches of the
whenexpression repeat the samecolors,shape, andfillMaxWidth()configuration. While the current implementation is clear and correct, you could reduce duplication by extracting shared properties into local variables or using a helper function.This is a minor maintainability improvement—the existing code functions properly.
♻️ Example refactor
`@OptIn`(ExperimentalFoundationApi::class) `@Composable` fun ExpressiveCard( modifier: Modifier = Modifier, onClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null, content: `@Composable` () -> Unit, ) { + val cardColors = CardDefaults.elevatedCardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainer, + ) + val cardShape = RoundedCornerShape(32.dp) + val cardModifier = modifier.fillMaxWidth() + when { onClick != null && onLongClick != null -> { ElevatedCard( - modifier = modifier - .fillMaxWidth() + modifier = cardModifier .combinedClickable( onClick = onClick, onLongClick = onLongClick, ), - colors = CardDefaults.elevatedCardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainer, - ), - shape = RoundedCornerShape(32.dp), + colors = cardColors, + shape = cardShape, content = { content() }, ) } // ... similar for other branches } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.kt` around lines 14 - 69, The ExpressiveCard implementation repeats ElevatedCard configuration (colors, shape, modifier.fillMaxWidth()) across branches; refactor by extracting shared values into local vals (e.g., val cardModifier = modifier.fillMaxWidth(), val cardColors = CardDefaults.elevatedCardColors(...), val cardShape = RoundedCornerShape(32.dp)) and then call ElevatedCard once in each branch using those locals while only varying the click-related parameters (combinedClickable modifier vs onClick vs neither) so duplication is removed but behavior of ExpressiveCard (onClick/onLongClick handling) remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@feature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchViewModel.kt`:
- Around line 158-174: observeHiddenRepos currently removes hidden entries from
state.repositories which breaks unhide and is inconsistent with
observeSeenRepos; instead, update observeHiddenRepos to mirror observeSeenRepos
by mapping over current.repositories and toggling each item's hidden flag based
on the collected ids (i.e., set item.isHidden = id in ids) rather than filtering
them out, then update state with the new repositories and hiddenRepoIds so
computeVisibleRepos can handle display/reactivity and OnUndoHideRepository
restores immediately.
---
Nitpick comments:
In
`@core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.kt`:
- Around line 14-69: The ExpressiveCard implementation repeats ElevatedCard
configuration (colors, shape, modifier.fillMaxWidth()) across branches; refactor
by extracting shared values into local vals (e.g., val cardModifier =
modifier.fillMaxWidth(), val cardColors = CardDefaults.elevatedCardColors(...),
val cardShape = RoundedCornerShape(32.dp)) and then call ElevatedCard once in
each branch using those locals while only varying the click-related parameters
(combinedClickable modifier vs onClick vs neither) so duplication is removed but
behavior of ExpressiveCard (onClick/onLongClick handling) remains unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 973d5b8d-8f89-41ea-8291-045e6c72291f
📒 Files selected for processing (34)
core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/17.jsoncore/data/src/androidMain/kotlin/zed/rainxch/core/data/local/db/initDatabase.ktcore/data/src/androidMain/kotlin/zed/rainxch/core/data/local/db/migrations/MIGRATION_16_17.ktcore/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.ktcore/data/src/commonMain/kotlin/zed/rainxch/core/data/local/db/AppDatabase.ktcore/data/src/commonMain/kotlin/zed/rainxch/core/data/local/db/dao/HiddenRepoDao.ktcore/data/src/commonMain/kotlin/zed/rainxch/core/data/local/db/entities/HiddenRepoEntity.ktcore/data/src/commonMain/kotlin/zed/rainxch/core/data/repository/HiddenReposRepositoryImpl.ktcore/domain/src/commonMain/kotlin/zed/rainxch/core/domain/model/HiddenRepo.ktcore/domain/src/commonMain/kotlin/zed/rainxch/core/domain/repository/HiddenReposRepository.ktcore/presentation/src/commonMain/composeResources/files/whatsnew/17.jsoncore/presentation/src/commonMain/composeResources/values-ar/strings-ar.xmlcore/presentation/src/commonMain/composeResources/values-bn/strings-bn.xmlcore/presentation/src/commonMain/composeResources/values-es/strings-es.xmlcore/presentation/src/commonMain/composeResources/values-fr/strings-fr.xmlcore/presentation/src/commonMain/composeResources/values-hi/strings-hi.xmlcore/presentation/src/commonMain/composeResources/values-it/strings-it.xmlcore/presentation/src/commonMain/composeResources/values-ja/strings-ja.xmlcore/presentation/src/commonMain/composeResources/values-ko/strings-ko.xmlcore/presentation/src/commonMain/composeResources/values-pl/strings-pl.xmlcore/presentation/src/commonMain/composeResources/values-ru/strings-ru.xmlcore/presentation/src/commonMain/composeResources/values-tr/strings-tr.xmlcore/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xmlcore/presentation/src/commonMain/composeResources/values/strings.xmlcore/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.ktcore/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeAction.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeRoot.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeState.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeViewModel.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchAction.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchRoot.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchState.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchViewModel.kt
Greptile Summary
Confidence Score: 3/5Not safe to merge as-is; multiple P1s leave users on blank screens when manual hide is used without "Hide seen" enabled. Four P1 findings across SearchRoot (spinner, banner, LaunchedEffect guard) and SearchViewModel (totalCount mismatch), plus the HomeRoot auto-paginate dead-end — all confirmed defects on the new manual-hide path rather than speculative risks. The data layer (migration, DAO, repository) is correct and well-structured. Score is pulled below the P1 ceiling of 4 due to multiple independent issues affecting the same core user flow. feature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchRoot.kt and SearchViewModel.kt require the most attention; HomeRoot.kt needs the auto-paginate guard widened. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User long-presses RepositoryCard] --> B[DropdownMenu shown]
B --> C[OnHideRepository action]
C --> D[HiddenReposRepository.hide]
D --> E[Room: INSERT INTO hidden_repos]
E --> F[getAllHiddenRepoIds Flow emits]
F --> G[HomeVM / SearchVM: hiddenRepoIds updated]
G --> H{computeVisibleRepos}
H -->|repo.id in hiddenRepoIds| I[Filtered out of visibleRepos]
H -->|repo.id not hidden| J[Shown in grid]
I --> K[Grid re-renders — card disappears]
subgraph SearchRoot issues
L[LaunchedEffect: auto-paginate] -->|gates on isHideSeenEnabled only| M[Never fires for manual-hide path]
N[Spinner: searching for unseen repos] -->|gates on isHideSeenEnabled only| O[Never shown for manual-hide path]
P[Banner: all results hidden] -->|gates on isHideSeenEnabled only| Q[Never shown — blank screen]
end
subgraph Management screen
R[Tweaks > Hidden Repositories]
R --> S[HiddenRepositoriesViewModel observes getAllHiddenRepos]
S --> T[OnUnhide / OnUnhideAll actions]
T --> U[HiddenReposRepository.unhide / clearAll]
U --> V[Room: DELETE FROM hidden_repos]
V --> F
end
|
7085119 to
e5f359b
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@feature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeViewModel.kt`:
- Around line 526-542: The HomeViewModel currently launches hiding/unhiding
calls (HomeAction.OnHideRepository and HomeAction.OnUndoHideRepository) without
handling exceptions; wrap the hiddenReposRepository.hide(...) and
hiddenReposRepository.unhide(...) calls inside try/catch blocks within the
viewModelScope.launch in HomeViewModel so any thrown exception is caught, log or
surface the error (e.g., via a logger or a UI error state update) and ensure you
update or rollback UI state predictably on failure; specifically modify the
handling for HomeAction.OnHideRepository and HomeAction.OnUndoHideRepository to
catch Throwable around hiddenReposRepository.hide and
hiddenReposRepository.unhide and perform appropriate error logging/state
emission instead of letting the exception propagate.
In
`@feature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchViewModel.kt`:
- Around line 747-763: SearchViewModel currently launches database writes in the
viewModelScope for SearchAction.OnHideRepository (calling
hiddenReposRepository.hide) and SearchAction.OnUndoHideRepository (calling
hiddenReposRepository.unhide) without error handling; wrap each repository call
inside the existing viewModelScope.launch in a try-catch block that catches
Exception, then handle failures by logging the error and emitting an error
event/state (or calling the existing error reporting mechanism) so coroutine
exceptions are not uncaught and the UI can react to failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 467639a4-e7c3-499e-a3fe-0c791dce65bb
📒 Files selected for processing (5)
core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.ktcore/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeRoot.ktfeature/home/presentation/src/commonMain/kotlin/zed/rainxch/home/presentation/HomeViewModel.ktfeature/search/presentation/src/commonMain/kotlin/zed/rainxch/search/presentation/SearchViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (2)
- core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/ExpressiveCard.kt
- core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.kt
Sprint 2 task E11. Survey #4 — "Hide seen" is too strict; users want manual hide.
What landed:
hidden_reposRoom table (v17 migration) + DAO +HiddenReposRepositoryin core/domain + impl in core/data.RepositoryCardopens aDropdownMenuwith "Hide repository" (VisibilityOfficon).ExpressiveCardextended with optionalonLongClickso the existing tap ripple stays intact viacombinedClickable.HiddenReposRepository, observe hidden IDs, drop already-loaded repos that get hidden so the grid reacts immediately.mapReposToUi/computeVisibleReposfilter forward on subsequent page loads.OnHideRepository/OnUndoHideRepositoryactions on both VMs persist via repo. Library/Apps screen unaffected — install state still authoritative.Deferred to follow-up:
Compile-verified:
:composeApp:compileDebugKotlinAndroidBUILD SUCCESSFUL.Summary by CodeRabbit
New Features
Management
Persistence
Presentation
Localization
Documentation