summaryrefslogtreecommitdiff
path: root/apps/web/app/reader
Commit message (Collapse)AuthorAgeFilesLines
* fix: include feed name in unsubscribe notificationHEADmainFuwn2026-02-121-0/+2
|
* fix: keep scroll position stable when entry list re-sorts after read state ↵Fuwn2026-02-121-6/+7
| | | | change
* fix: prioritise unread entries server-side so they appear in all-entries viewFuwn2026-02-121-16/+11
|
* feat: add drag-and-drop reordering for feeds, folders, and custom feedsFuwn2026-02-121-296/+734
|
* feat: add previous/next navigation buttons on mobile detail viewFuwn2026-02-101-9/+36
|
* fix: query entry state directly instead of relying on unfiltered timelineFuwn2026-02-101-9/+26
| | | | | | The detail panel called useTimeline() with no args, creating a separate cache from the entry list's filtered query. Entries not in the first 50 of the global timeline had isSaved/isRead stuck at false.
* fix: let display density apply to main content panelFuwn2026-02-101-1/+1
|
* fix: exclude hidden feeds from total/folder unread counts onlyFuwn2026-02-101-5/+9
| | | | | | Reverts the DB-level filter so individual hidden feeds still show their own unread badge. Filters client-side in totalUnreadCount and getFolderUnreadCount instead.
* feat: add scrollbar style setting (themed/native/hidden)Fuwn2026-02-101-0/+25
| | | | | Themed scrollbars (default) use 6px thin bars matching the existing colour palette. Synced to body via class toggle in Providers.
* fix: remove font size selector, always use default text-baseFuwn2026-02-102-24/+1
|
* feat: add unread priority option to push unread entries to topFuwn2026-02-102-1/+35
| | | | | | Adds a persisted appearance setting (disabled by default) that partitions the entry list into unread-first, preserving original order within each group.
* feat: gate offline reading to pro and developer plansFuwn2026-02-102-1/+11
| | | | | | | Service worker now only caches Supabase REST responses when the user's tier allows offline reading. Client syncs tier status to SW via postMessage after profile loads. Free users see a descriptive offline banner instead of stale cached data.
* feat: add automatic timeline refresh with scroll position preservationFuwn2026-02-102-0/+43
| | | | | | | New appearance setting (disabled by default) that silently refreshes the entry list when new entries arrive, provided the user is scrolled to the top. Falls back to notification when scrolled down to avoid disrupting reading position.
* feat: scoped mark-all-read, share enhancements, notification z-indexFuwn2026-02-103-9/+63
| | | | | | | | | - Mark all as read now scopes to current feed/folder instead of all - Added undo button to mark-all-read toast notification - Share notes can be toggled between public and private visibility - Track share view count and display in shares list - Activity-based share expiry: views reset the expiry timer - Fixed notification panel z-index layering behind content area
* refactor: use Supabase Auth display name instead of custom columnFuwn2026-02-101-10/+3
| | | | | | Migrate existing display names from user_profiles to auth.users user_metadata. Drop display_name column from user_profiles. Frontend now reads from auth user metadata and updates via auth.updateUser().
* fix: reduce lint warnings from 34 to 0Fuwn2026-02-1014-34/+20
| | | | | | | | | Disable no-img-element (RSS reader needs <img> for arbitrary external URLs). Remove unused variables/imports and redundant getUser() calls guarded by middleware. Fix exhaustive-deps by adding stable deps, wrapping handlers in useCallback, and suppressing intentional omissions. Fix ref cleanup in use-realtime-entries. Allow triple-slash TS reference directives in no-comments rule.
* fix: P0 correctness/security fixes and P1 lint error resolutionFuwn2026-02-095-26/+44
| | | | | | | | | | | P0: add missing 'developer' case to check_custom_feed_limit trigger, scope user_entry_states join to authenticated user in API v1 entries, replace in-memory rate limiting with Supabase-backed check_rate_limit RPC. P1: fix all 9 ESLint errors — useSyncExternalStore for useIsMobile, restructure WebhookSection to avoid set-state-in-effect, move ref mutations into useEffect, replace <a> with <Link> on shared page, ignore generated public/sw.js in eslint config.
* feat: offline support tier 2 — prefetch entry content and SW runtime cachingFuwn2026-02-091-5/+10
| | | | | | | Prefetch content_html for the first 10 timeline entries in the background so they are available offline without needing to click each one. Add NetworkFirst runtime caching in service worker for Supabase REST GET requests (24h expiry, 200 entry limit).
* feat: offline support tier 1 — IndexedDB query persistence and offline bannerFuwn2026-02-092-1/+37
| | | | | | Persist React Query cache to IndexedDB via idb-keyval so timeline, entry details, subscriptions, and other read data survive page reloads and brief offline periods. Add network status banner in reader layout.
* fix: add spacing between collapsible appearance settings sectionsFuwn2026-02-091-1/+1
|
* ui: group appearance settings into collapsible sectionsFuwn2026-02-091-197/+228
|
* ui: reorder sidebar footer, import/export tab, and subscription actionsFuwn2026-02-093-47/+47
|
* feat: add per-feed "hide from timeline" optionFuwn2026-02-093-1/+21
|
* fix: elevate to AAL2 before password/email change when MFA is enabledFuwn2026-02-091-2/+62
|
* feat: truncate action bar button labels on mobile portraitFuwn2026-02-081-2/+2
|
* fix: mobile scroll preservation, bottom toolbar for detail panelFuwn2026-02-082-66/+84
|
* feat: add toolbar position setting (top or bottom)Fuwn2026-02-082-82/+115
|
* feat: enforce tier-based history retention (14d free, 90d pro/dev)Fuwn2026-02-081-1/+1
| | | | | | Replace unlimited history claim with honest 90-day retention for paid tiers. Timeline and search RPCs now filter by tier-appropriate retention window.
* feat: show tier-specific welcome message on subscription activationFuwn2026-02-081-1/+2
|
* feat: add support email to account settingsFuwn2026-02-081-0/+12
|
* feat: share with highlighted excerpt and fix auth redirect URLsFuwn2026-02-082-0/+67
| | | | | | | | | Add "share" button to text selection toolbar so users can share an entry with a highlighted passage visible to visitors. The public share page renders the highlight and scrolls to it on load. Also fix magic link and password reset redirects to use NEXT_PUBLIC_APP_URL instead of window.location.origin so emails link to the production domain.
* fix: share clipboard write for Safari transient activationFuwn2026-02-081-25/+43
| | | | | | | - Use ClipboardItem with Promise to preserve user gesture context - Fall back to showing share URL in toast if clipboard is unavailable - Derive app origin from request URL when NEXT_PUBLIC_APP_URL is unset - Add onError handlers to share/unshare mutations
* feat: add feed management features and fix subscribe_to_feed bugsFuwn2026-02-084-47/+325
| | | | | | | | | | | | | - Fix subscribe_to_feed overload ambiguity by dropping old 4-param version - Fix vault permission error by using vault.create_secret instead of direct INSERT - Add duplicate subscription check with clear error message - Add unmute confirmation dialog matching unsubscribe pattern - Add feed button in subscriptions settings page - Add inline rename for feeds, folders, and custom feeds from reader header - Add drag and drop feeds between folders in sidebar - Add credential management UI (add/update) for pro/developer tier - Add add_feed_credentials RPC to convert public feeds to authenticated - Enable pgsodium extension for vault crypto operations
* feat: implement authenticated feed support across worker and web appFuwn2026-02-083-0/+58
| | | | | | | | | | Wire up the full authenticated feeds pipeline: - Worker resolves credentials from Supabase Vault for authenticated feeds - Worker sets owner_id on entries for per-user dedup - query_param auth now parses name=value format - Add-feed dialog shows auth type + credential fields for pro/developer - Subscribe mutation passes credentials to RPC - Sidebar and settings show [auth] indicator for authenticated feeds
* fix: clicking notifications button while panel is open now correctly ↵Fuwn2026-02-082-1/+4
| | | | dismisses it
* fix: notification count alignment — add flex to button so ml-auto pushes ↵Fuwn2026-02-081-1/+1
| | | | count to right edge
* feat: add feed URL editing in subscription settings, fix notification badge ↵Fuwn2026-02-083-4/+73
| | | | styling and HTML entity decoding
* feat: add option to show favicons next to feed names in entry listFuwn2026-02-082-0/+44
|
* feat: add appearance option to toggle folders above/below ungrouped feeds in ↵Fuwn2026-02-082-99/+128
| | | | sidebar
* feat: display folders above ungrouped feeds in sidebar, add ↵Fuwn2026-02-082-39/+77
| | | | delete-all-custom-feeds to danger zone
* fix: space/shift+space scrolls focused panel, revert content font, fix share ↵Fuwn2026-02-074-36/+4
| | | | | | | | | modal text Space/Shift+Space now scrolls whichever panel is focused (entry list, detail panel, or sidebar) instead of only working in the detail panel. Removed content font setting. Fixed share modal placeholder casing and ellipsis spacing.
* feat: resolve 7 pre-ship QoL itemsFuwn2026-02-075-6/+118
| | | | | | | | | | | | | | | - Space/Shift+Space: page down/up in detail panel (80% scroll) - Content font: sans-serif/serif/monospace selector in appearance settings, applied to article content in detail panel - Accessibility: entry-list-item uses button instead of div, folder toggles have aria-expanded, shortcut keys have aria-labels - Share notes: replaced window.prompt with proper modal dialog matching existing UI patterns - Worker .env.example: template with all 10 environment variables - Worker poisoned messages: archive unprocessable queue messages instead of leaving them stuck forever - Worker pool Submit: check return value, reschedule dropped feeds 30s into the future, log warnings for rejected submissions
* fix: dynamically calculate detail panel equal split from current layoutFuwn2026-02-071-4/+9
|
* fix: reset panel sizes without page reload, prevent partial-data max width ↵Fuwn2026-02-073-37/+62
| | | | | | | | | | | | clamping Use imperative groupRef API to resize panels instantly instead of writing to localStorage and calling window.location.reload(). Register reset callbacks in Zustand store from layout components. Change sidebarMaxWidth early return from && to || so the generous 35% fallback is used until both subscriptions and custom feeds have loaded, preventing intermittent clamping to minimum size.
* fix: reset sidebar to midpoint of min/max, detail to 50/50 splitFuwn2026-02-071-6/+32
| | | | | | Read current panel dimensions from DOM, compute sidebar midpoint as (192px + maxWidth) / 2, and detail as equal halves. Write computed values to localStorage before reload.
* fix: prevent sidebar max width from clamping persisted size on loadFuwn2026-02-071-0/+1
| | | | | | Return 35% max until subscriptions/feeds data loads. Previously the useMemo computed a small max from just nav items on first render, causing the library to clamp and overwrite the stored sidebar width.
* fix: persist sidebar size across collapse/expand cyclesFuwn2026-02-071-1/+1
| | | | | | When sidebar is collapsed, the Group fires onLayoutChanged with only main-content, overwriting the stored sidebar size. Pass undefined for onLayoutChanged when collapsed so the stored layout is preserved.
* fix: api key prefix rename, revoke fix, and webhook validationFuwn2026-02-071-2/+2
| | | | | | Rename API key prefix from asn_ to asa_, fix key revoke by aligning response property names with frontend interface, and add server/client validation to prevent enabling webhooks without a URL.
* feat: dynamically compute sidebar max width from item text widthsFuwn2026-02-071-2/+105
| | | | | | Measures all sidebar items (nav links, feeds, folders, custom feeds, footer) using Canvas measureText to determine the narrowest width that avoids truncation, then passes it as the Panel maxSize.
* fix: use fixed rem-based sidebar min/default with whitespace-nowrapFuwn2026-02-073-79/+7
| | | | | | | | The dynamic measurement approach failed because the library caches Panel constraints at mount and ignores state-driven prop updates. Now uses fixed rem values (12rem min, 16rem default) which scale with font size, plus whitespace-nowrap on all sidebar items to prevent text wrapping at any width.