feat(files): add per-user file favorites#191
Closed
zjean wants to merge 36 commits intoSync-in:mainfrom
Closed
Conversation
Introduces the files_favorites table (userId + fileId composite PK, cascade deletes, user_idx index) and a fileIsFavoriteForUserSQL helper for use in query-layer EXISTS checks.
…ailing comma, remove redundant fields
Thin service that delegates getFavorites/addFavorite/removeFavorite to FilesQueries; registered in FilesModule providers and exports alongside FilesRecents. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…rom FileProps base type
…igation Introduces FileFavorite interface with a server-computed navPath (personal/ space-alias/path) so goToFile can navigate correctly instead of always landing at personal root. Also copies mime icon styles into the widget scss. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add isFavorite = false to FileModel states (populated via Object.assign from backend) - Enable withIsFavorite: true in spaces.controller.ts browseSpace call - Thread withIsFavorite through SpacesBrowser.browse, parseDB, and updateDBFiles - Import faStar (solid) and faStarRegular (regular) into spaces-browser component - Add toggleFavorite() method calling filesService.toggleFavorite with optimistic local flip - Render star badge before comments badge in file row info column
…navPath display, loadFavorites set(), fileId index, migration NULL guard, ParseIntPipe on limit, breadcrumb URL, limit cap Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Remove unused FAVORITES_TITLE import from favorites.component.ts - Add overflow: hidden to .recent-item-card__media in widget scss - Use sql<boolean>.mapWith(Boolean) for isFavorite in getFavorites; update FileFavorite interface to boolean - Filter trashed files from getFavorites with eq(files.inTrash, false) - Accessibility: alt text on mime icon img, aria-label on toggle and file buttons in widget - Accessibility: make star toggle in spaces-browser keyboard-accessible (keydown.enter/space, role, tabindex, aria-label, aria-pressed) - Spec: assert NotFoundException type in addFavorite not-accessible test Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…s KeyboardEvent not MouseEvent
…EFT JOIN was unreliable
…ient, trust SpaceGuard upstream
…atches recents panel styling
…t on favorites page
… correct card styling
…re indexing pattern Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ix id existence check
… already-indexed files
…s via space.dbFile, share roots via shareExternalId
…cess — mirrors getRecentsFromUser pattern
…rollback + remove dev-only files + clean SQL helper
…mpty on required DTO fields, test format
…rmatting, remove unused userId param
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
files_favoritesjoin table (userId,fileId,createdAt) with cascade deletes on both FKs and a composite primary keyGET /spaces/favorites,POST /spaces/favorite,DELETE /spaces/favorite/:fileIdisFavorite: booleanincluded in file browse results via a newwithIsFavoriteoption onbrowseFiles(EXISTS subquery, same pattern aswithHasComments)getRecentsFromUserpatternFileFavoriteModelPOST /spaces/favoriteaccepts full file context (FavoriteFileDto) and performs a find-or-create on thefilestable so unindexed filesystem entries (negative inode IDs) can be starred immediately — same pattern as share creationDatabase
API
/api/app/spaces/favorites/api/app/spaces/favorite/api/app/spaces/favorite/:fileIdTest plan