Add account-backed default collection setting - #145
Conversation
Add a "Default collection" option to the extension settings that is populated from the configured Linkwarden account, so only a valid collection can be chosen. The selected collection (stored by id and name) pre-fills the collection select box in the popup when saving a new link. - Replace the previously commented-out free-text default collection field in the options form with a Select populated from the account's collections via the existing collections API. - Persist the chosen collection id alongside its name in the config. - Resolve the default collection to its full object (id/ownerId/name) in the bookmark form once collections load, so links are saved to the exact collection while preserving any manual selection. https://claude.ai/code/session_01PP23rDThGU2FEtphX7C7pj
*Total -- 605.23kb -> 432.42kb (28.55%) /assets/chrome.png -- 3.70kb -> 2.54kb (31.34%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-512@2x.png -- 279.79kb -> 192.67kb (31.14%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-512@1x.png -- 106.93kb -> 76.90kb (28.08%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-256@2x.png -- 106.93kb -> 76.90kb (28.08%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-256@1x.png -- 41.79kb -> 31.30kb (25.1%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-128@2x.png -- 41.79kb -> 31.30kb (25.1%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-128@1x.png -- 14.20kb -> 11.50kb (19%) /safari/Linkwarden/Linkwarden/Assets.xcassets/AppIcon.appiconset/mac-icon-32@2x.png -- 4.83kb -> 4.35kb (9.85%) /assets/firefox.png -- 5.25kb -> 4.93kb (6.12%) Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Address review feedback: - Add an explicit "Unorganized" option to the default collection selector so it can be chosen/reverted without a full Reset, and handle the non-numeric sentinel value in the change handler. - Apply the default collection in the popup only once (on first load) so a later React Query refetch never overrides the user's manual choice, and fall back to name matching when the stored id no longer resolves. https://claude.ai/code/session_01PP23rDThGU2FEtphX7C7pj
Add account-backed default collection setting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… steps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for selecting and persisting a per-account default Linkwarden collection (by ID) and updates the UI to load collections from the configured account.
Changes:
- Extend config/options schemas to include
defaultCollectionId. - Update Options and Bookmark forms to fetch collections and apply the configured default collection by ID (with a name-based fallback).
- Update README installation instructions and add an
allowScriptsentry inpackage.json.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/@/lib/validators/optionsForm.ts | Adds defaultCollectionId to options form validation schema. |
| src/@/lib/validators/config.ts | Adds defaultCollectionId to persisted config validation schema. |
| src/@/components/OptionsForm.tsx | Fetches collections, adds a default-collection selector, saves defaultCollectionId. |
| src/@/components/BookmarkForm.tsx | Applies saved defaultCollectionId to preselect the collection when saving links. |
| package.json | Adds allowScripts configuration for esbuild. |
| README.md | Documents default collection feature and expanded unpacked-load steps for browsers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return response.data.response.sort((a, b) => | ||
| a.pathname.localeCompare(b.pathname) | ||
| ); |
There was a problem hiding this comment.
Fixed in the latest commit: changed to [...response.data.response].sort(...) so the fetched array is copied before sorting, leaving the React Query cache entry unmodified. (toSorted is ES2023; the project targets ES2020, so the spread approach is used instead.)
| value={ | ||
| field.value ? String(field.value) : 'unorganized' | ||
| } |
There was a problem hiding this comment.
Fixed: replaced field.value ? with field.value !== undefined ? for an explicit check that correctly handles any numeric value, including a hypothetical 0.
| const match = | ||
| (config.defaultCollectionId | ||
| ? collections.find((c) => c.id === config.defaultCollectionId) | ||
| : undefined) ?? | ||
| collections.find((c) => c.name === config.defaultCollection); |
There was a problem hiding this comment.
The pathname-based fallback would not work here because the value stored in defaultCollection is the collection name, not the pathname — so there is nothing to match against. That said, the concern about name ambiguity is valid. The upstream UI actually has this field commented out, so no real users have a stored name to migrate. The name-based fallback has therefore been removed entirely. If a stored ID no longer resolves (e.g. the collection was deleted), the popup now shows a destructive toast asking the user to update the setting in Options.
| export const configSchema = z.object({ | ||
| baseUrl: z.string().url(), | ||
| defaultCollection: z.string().optional().default('Unorganized'), | ||
| defaultCollectionId: z.number().optional(), | ||
| apiKey: z.string(), | ||
| syncBookmarks: z.boolean().optional().default(false), | ||
| }); |
There was a problem hiding this comment.
Fixed in both config.ts and optionsForm.ts: changed to z.coerce.number().int().positive().optional(). The coerce handles any storage serialisation quirk, while .int().positive() rejects zero and non-integer values so the constraint is stricter, not looser.
- Avoid mutating React Query cache: spread-copy before sort in OptionsForm - Use explicit undefined check instead of truthiness for collection id - Drop name-based fallback in BookmarkForm; show toast when stored id no longer resolves - Harden Zod schemas: z.coerce.number().int().positive() for defaultCollectionId Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps the npm_and_yarn group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [axios](https://github.com/axios/axios) | `1.13.2` | `1.18.0` | | [postcss](https://github.com/postcss/postcss) | `8.5.6` | `8.5.26` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `7.2.0` | `8.2.1` | | [brace-expansion](https://github.com/juliangruber/brace-expansion) | `1.1.12` | `1.1.18` | | [flatted](https://github.com/WebReflection/flatted) | `3.2.7` | `3.4.4` | | [js-yaml](https://github.com/nodeca/js-yaml) | `4.1.0` | `4.3.1` | | [minimatch](https://github.com/isaacs/minimatch) | `3.1.2` | `3.1.5` | | [picomatch](https://github.com/micromatch/picomatch) | `2.3.1` | `removed` | Updates `axios` from 1.13.2 to 1.18.0 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.13.2...v1.18.0) Updates `postcss` from 8.5.6 to 8.5.26 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.5.6...8.5.26) Updates `vite` from 7.2.0 to 8.2.1 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.2.1/packages/vite) Updates `brace-expansion` from 1.1.12 to 1.1.18 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](juliangruber/brace-expansion@v1.1.12...v1.1.18) Updates `flatted` from 3.2.7 to 3.4.4 - [Commits](WebReflection/flatted@v3.2.7...v3.4.4) Updates `follow-redirects` from 1.15.6 to 1.16.0 - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](follow-redirects/follow-redirects@v1.15.6...v1.16.0) Updates `form-data` from 4.0.4 to 4.0.6 - [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md) - [Commits](form-data/form-data@v4.0.4...v4.0.6) Updates `js-yaml` from 4.1.0 to 4.3.1 - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md) - [Commits](nodeca/js-yaml@4.1.0...4.3.1) Updates `minimatch` from 3.1.2 to 3.1.5 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](isaacs/minimatch@v3.1.2...v3.1.5) Updates `nanoid` from 3.3.11 to 3.3.18 - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/3.3.18/CHANGELOG.md) - [Commits](ai/nanoid@3.3.11...3.3.18) Removes `picomatch` --- updated-dependencies: - dependency-name: axios dependency-version: 1.18.0 dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: postcss dependency-version: 8.5.26 dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: vite dependency-version: 8.2.1 dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: brace-expansion dependency-version: 1.1.18 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: flatted dependency-version: 3.4.4 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: follow-redirects dependency-version: 1.16.0 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: form-data dependency-version: 4.0.6 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: js-yaml dependency-version: 4.3.1 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: minimatch dependency-version: 3.1.5 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: nanoid dependency-version: 3.3.18 dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: picomatch dependency-version: dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com>
[ImgBot] Optimize images
…_and_yarn-f74187a1f2 Bump the npm_and_yarn group across 1 directory with 11 updates
Adds claude-code-review.yml (automatic PR review) and claude.yml (@claude mention trigger), matching the hardened template used across other repos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X85Bsow8BVidsnkjRUZGTg
Summary
Changes
src/@/components/OptionsForm.tsxsrc/@/components/BookmarkForm.tsxsrc/@/lib/validators/config.tsdefaultCollectionIdfieldsrc/@/lib/validators/optionsForm.tsdefaultCollectionIdfieldREADME.mdpackage.jsonallowScriptsentry foresbuild(suppresses install warning)Test plan
defaultCollectionId), confirm name-based fallback still resolves the collection🤖 Generated with Claude Code