feat: custom feed icons & different edit interaction - #2284
Conversation
- Updated pubky-app-specs dependency in package.json and package-lock.json to version 0.7.0. - Added icon picker feature in multiple language files (ar.json, de.json, en.json, es.json, fr.json, it.json, ja.json, pt-BR.json, zh.json) to allow users to select custom icons for feeds. - Implemented tests for the new DynamicLucideIcon component to ensure proper rendering and fallback behavior. - Enhanced CustomFeedDialog to support icon selection and display appropriate icons based on user input.
- Enhanced the edit button styles in the FeedNavigation component by adding new classes for rounded corners, transparent background, and transition effects. - Updated the SVG icon size for consistency. - Adjusted snapshots to reflect the new button styles and icon size changes.
- Improved tests for the IconPickerDialog component by adding checks for loading states and ensuring proper rendering after animations. - Updated the test suite to include mobile-specific snapshots for the icon picker grid. - Refactored the component to support virtualized rendering for better performance on mobile and desktop views. - Adjusted the handling of scroll and query changes to improve user experience.
- Removed unnecessary mock for useCustomFeed hook and adjusted tests to directly pass the feed prop to CustomFeedDialog. - Updated tests to ensure the dialog behaves correctly in both edit and create modes, including enabling/disabling inputs based on feed presence. - Enhanced snapshot tests to reflect the latest changes in the dialog's rendering logic. - Cleaned up redundant test cases to streamline the test suite.
Greptile SummaryAdds selectable custom Lucide icons to custom feeds.
Confidence Score: 4/5The unknown-icon overwrite should be fixed before merging because an unrelated feed edit can silently destroy icon metadata created by another client. The edit form replaces unrecognized stored icons with the default and submits all fields, defeating the lower-layer preservation behavior and persisting the replacement locally and remotely. Files Needing Attention: src/hooks/useCustomFeedForm/useCustomFeedForm.types.ts, src/hooks/useCustomFeedForm/useCustomFeedForm.ts
|
| Filename | Overview |
|---|---|
| src/hooks/useCustomFeedForm/useCustomFeedForm.types.ts | Defines form validation and stored-feed mapping, but converting unknown icons to the default causes destructive round trips. |
| src/hooks/useCustomFeedForm/useCustomFeedForm.ts | Centralizes create, update, delete, navigation, and toast behavior; full-form update submission contributes to overwriting unknown icons. |
| src/core/application/feed/feed.ts | Persists icon metadata and provides legacy defaults while preserving the existing local/homeserver migration flow. |
| src/components/organisms/IconPickerDialog/IconPickerDialog.tsx | Adds a searchable and virtualized responsive Lucide icon picker. |
| src/components/organisms/FeedNavigation/FeedNavigation.tsx | Displays custom icons and exposes separate accessible edit actions for every saved feed. |
| src/components/organisms/CustomFeedDialog/CustomFeedDialog.tsx | Integrates the icon picker and refactored form controls into create and edit dialogs. |
| src/core/pipes/feed/feed.validators.ts | Sanitizes missing or oversized icons while deliberately preserving valid names unknown to this client. |
Sequence Diagram
sequenceDiagram
participant User
participant Dialog as CustomFeedDialog
participant Form as useCustomFeedForm
participant Controller as FeedController
participant App as FeedApplication
participant Local as IndexedDB
participant HS as Homeserver
User->>Dialog: Select icon and save
Dialog->>Form: submit()
Form->>Controller: commitCreate/commitUpdate
Controller->>App: persist normalized feed
App->>Local: write feed with icon
App->>HS: PUT feed JSON with icon
Reviews (1): Last reviewed commit: "test: refactor CustomFeedDialog tests fo..." | Re-trigger Greptile
🚀 Preview DeploymentURL: https://pubky-app-pr-2284-fzxmjul7ya-oa.a.run.app
|
…eedNavigation component - Introduced a new translation key "moreFeeds" in Arabic, German, English, Spanish, French, Italian, Japanese, Portuguese, and Chinese language files to improve user experience in navigating feeds. - Updated the FeedNavigation component to support displaying additional feeds in a popover for better accessibility on larger screens. - Enhanced tests and snapshots to reflect the new functionality and ensure consistent behavior across different screen sizes.
Co-authored-by: Cursor <cursoragent@cursor.com>
…oved reactivity - Updated the CustomFeedDialog component to utilize useWatch from react-hook-form, enhancing the reactivity of form field values. - Simplified the handleReachChange function to directly set form values, ensuring consistent updates for the reach selection. - Adjusted the domainTags initialization to default to an empty array when not set, improving robustness.
…ctor visibility - Implemented a new test to verify that the profile tags are capped at five and that the emoji selector is hidden when the limit is reached. - The test simulates user input for profile tags and checks the attributes of the tag input field to ensure correct behavior.
secondl1ght
left a comment
There was a problem hiding this comment.
This is a nice improvement, a few things:
- The new dropdown picker to view hidden feeds doesn't match the design (using the video @olivert2025 shared in Slack as an example).
- On initial load the icons in the picker are fairly laggy, consider preloading these for a better UX. It's not critical because once they are cached they load faster, but is quite noticeable on first render.
- The close (X) button in the search input looks out of place with our app theme, it is blue but I've never seen this style anywhere else. It's also missing the pointer cursor on hover indicating it's clickable. We should use the standard white or grey colors to match. (Or even the primary brand green color would look better.)
- There is a visible flicker on page refresh where the default icons are shown temporarily before the real icons are used, we should fix that so the correct icons are always displayed.
And then there are a few comments from Claude that will follow.
|
From Claude: 1. Editing a feed silently overwrites a foreign client's icon. 2. 3. Virtualization constants are silently coupled to Tailwind classes. |
Both are coming from the same problem we're using dynamic which imports dynamic the specific icon without adding them directly to our bundle and makes an independent module in build time.
✅
Updated and Oliver give the okey |
This is okey, if is not from Lucide lets rewrite it, it's a more strong guard but I believe it's a good thing. This could change if we stop supporting lucide but I believe it's change in the paradigm of our code in that moment |
# Conflicts: # messages/ar.json # messages/de.json # messages/es.json # messages/fr.json # messages/it.json # messages/ja.json # messages/pt-BR.json # messages/zh.json # src/test/vrt/feed/__screenshots__/Home.vrt.test.tsx/home-feed-desktop-chromium-darwin.png # src/test/vrt/feed/__screenshots__/Home.vrt.test.tsx/home-feed-desktop-firefox-darwin.png # src/test/vrt/feed/__screenshots__/Home.vrt.test.tsx/home-feed-desktop-webkit-darwin.png
Specs 0.7.0 createFeed rejects icons with characters outside [a-z0-9-]; sanitizeIcon passing such a value through made the per-feed bootstrap guard drop the whole feed from the user's list. Falling back to the default icon keeps the feed.
CustomFeedDialog migrated to useCustomFeedForm; nothing imports the mutation hook anymore.
…eedback - Load dynamic Lucide icons through a module-level IconNode cache: cached icons render synchronously on first paint, a loading icon shows an empty size-preserving svg instead of the wrong default glyph, and a failed chunk falls back to the default and retries on remount. - Preload feed icons when feed data lands and the picker's first window on dialog open, so first paint hits the cache. - Hide deprecated Lucide alias names from the picker grid (same glyph twice); aliases stay valid for stored feeds. - Replace the native webkit search-cancel button with a themed clear button (pointer cursor, muted foreground) and refocus on clear. - Keep unknown-but-valid foreign icon names intact in the edit form so an unrelated edit does not overwrite another client's icon. - Move focus into the edit dialog when its auto-focus is suppressed. - Document the virtualization constants' coupling to the grid classes. - Regenerate affected snapshots and darwin VRT baselines (chromium and firefox; the local webkit runner crashes before running any test).
|
Closing this PR in favor of #2353 and other PRs that are yet to come. |
- Feed navigation is now a tab bar on mobile too (v26): the selected tab shows icon + label, other tabs collapse to icon-only, Create is a plus icon; the strip sticks under the compact mobile header (Hot pattern) and the mobile right drawer falls back to Who to follow / Hot tags. - The first tab mirrors the selected reach (My network, All, Tagged as, ...) with the matching icon, via a shared REACH_FILTER_META map. - Custom feeds get a selectable Lucide icon (icon picker dialog, dynamic icon atom, spec 0.7.0 with the icon field synced to the homeserver), ported from PR #2284 and de-i18n-ized; feeds without an icon fall back to Activity. - CustomFeedDialog moves to a useCustomFeedForm hook (react-hook-form + zod); edit/delete only navigate away when you are viewing the edited feed, and config edits use replace since the old hash id is dead. - Pencil affordance: hover-revealed on desktop, always visible on the selected custom feed tab on mobile, with a larger hit area.
resolves #1898
resolves #1897
Description
Added Custom Icons following Lucide react library to Custom Feeds, added custom dialog to decide icons.
Modified different edit interaction of custom feeds
Demo video
Screen.Recording.2026-08-03.at.11.06.18.mov