[PR #2230] [MERGED] feat: Add unified reader settings with local overrides #2032

Closed
opened 2026-03-02 12:00:16 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/karakeep-app/karakeep/pull/2230
Author: @esimkowitz
Created: 12/7/2025
Status: Merged
Merged: 12/15/2025
Merged by: @MohamedBassem

Base: mainHead: reader-text-settings


📝 Commits (10+)

  • 73707b5 Add initial impl
  • 8194c85 fix some format inconsistencies, add indicator in user settings when local is out of sync
  • e41ef46 Fix sliders in user settings, unify constants and formatting
  • e5d4916 address CodeRabbit suggestions
  • 3f144a1 add mobile implementation
  • e6ffae9 address coderabbit nitpicks
  • 33145df fix responsiveness of the reader settings popover
  • c491281 Move more of the web UI strings to i18n
  • 0743458 update translations for more coverage
  • 9850e18 remove duplicate logic/definitions

📊 Changes

30 files changed (+4866 additions, -199 deletions)

View changed files

📝 .gitignore (+3 -0)
📝 apps/mobile/app/dashboard/(tabs)/settings.tsx (+12 -0)
📝 apps/mobile/app/dashboard/_layout.tsx (+8 -0)
📝 apps/mobile/app/dashboard/bookmarks/[slug]/index.tsx (+20 -7)
apps/mobile/app/dashboard/settings/reader-settings.tsx (+264 -0)
📝 apps/mobile/components/bookmarks/BookmarkLinkPreview.tsx (+31 -12)
📝 apps/mobile/components/bookmarks/BookmarkLinkTypeSelector.tsx (+3 -3)
📝 apps/mobile/lib/providers.tsx (+4 -1)
apps/mobile/lib/readerSettings.tsx (+93 -0)
📝 apps/mobile/lib/settings.ts (+8 -0)
📝 apps/web/app/dashboard/layout.tsx (+20 -17)
📝 apps/web/app/reader/[bookmarkId]/page.tsx (+12 -128)
apps/web/app/reader/layout.tsx (+39 -0)
📝 apps/web/app/settings/info/page.tsx (+2 -0)
📝 apps/web/app/settings/layout.tsx (+9 -6)
📝 apps/web/components/dashboard/preview/LinkContentSection.tsx (+23 -11)
apps/web/components/dashboard/preview/ReaderSettingsPopover.tsx (+457 -0)
apps/web/components/settings/ReaderSettings.tsx (+288 -0)
📝 apps/web/lib/i18n/locales/en/translation.json (+33 -0)
apps/web/lib/readerSettings.tsx (+155 -0)

...and 10 more files

📄 Description

Reader Text Settings

Adds standardized reader text settings with server-side storage for cross-device defaults and client-side local overrides.

Features

  • Three-tier settings precedence: Session (preview) → Local (device) → Server (global) → Defaults
  • Live preview: Adjust settings in the reader and see changes immediately before saving
  • Save options:
    • "This device" - saves to localStorage for device-specific preferences
    • "All devices" - saves to server for cross-device sync
  • Per-setting local overrides: Each setting can be individually overridden on a device, with clear buttons to revert to global defaults
  • Settings available in both views: Full-screen reader and preview pane both have the settings popover
  • Flicker-free server sync: Uses shared pending state to prevent UI flicker when saving to server

Changes

Shared Logic

  • packages/shared-react/hooks/reader-settings.ts - New shared hook with core reader settings logic used by both web and mobile:
    • pendingServerSave state prevents UI flicker during server sync
    • Proper cache invalidation on onSettled
    • Clears local overrides on successful server save
    • Exposes isSaving state
    • Supports optional session overrides for web live preview

Database & Backend

  • packages/db/schema.ts - Added readerFontSize, readerLineHeight, readerFontFamily columns to users table
  • packages/db/drizzle/0068_add_reader_settings.sql - Migration for new columns
  • packages/shared/types/users.ts - Added reader settings to zod schemas
  • packages/shared/types/readers.ts - New file with READER_DEFAULTS, READER_FONT_FAMILIES constants
  • packages/trpc/models/users.ts - Updated getSettings/updateSettings to handle reader settings

Web Frontend

  • apps/web/lib/readerSettings.tsx - Uses shared hook, adds React Context for session overrides (live preview)
  • apps/web/components/dashboard/preview/ReaderSettingsPopover.tsx - Shared popover component with live preview, +/- buttons for font size and line height, save options, per-setting local override indicators
  • apps/web/components/settings/ReaderSettings.tsx - Settings page component for global defaults with local override warning alert
  • apps/web/components/dashboard/preview/LinkContentSection.tsx - Added settings popover to preview pane
  • apps/web/app/reader/[bookmarkId]/page.tsx - Integrated settings into full-screen reader (ghost variant button)
  • apps/web/app/reader/layout.tsx - New layout with ReaderSettingsProvider
  • apps/web/app/dashboard/layout.tsx - Added ReaderSettingsProvider
  • apps/web/app/settings/layout.tsx - Added ReaderSettingsProvider
  • apps/web/lib/i18n/locales/en/translation.json - Added translation keys

Mobile App

  • apps/mobile/lib/readerSettings.ts - Uses shared hook with Expo SecureStore adapter, includes mobile-specific font family mappings
  • apps/mobile/app/dashboard/settings/reader-settings.tsx - Full settings page with sliders for font size/line height, font family picker, live preview, and save/clear options
  • apps/mobile/app/dashboard/bookmarks/[slug]/index.tsx - Added settings gear icon in reader header (visible when in reader mode)
  • apps/mobile/components/bookmarks/BookmarkLinkPreview.tsx - Applied reader settings to WebView content (font family, size, line height)
  • apps/mobile/app/dashboard/(tabs)/settings.tsx - Added Reader Settings link in settings tab
  • apps/mobile/app/dashboard/_layout.tsx - Added reader-settings route to navigation stack
  • apps/mobile/lib/settings.ts - Extended local settings type to include reader settings

UI Details

Web

  • Settings gear shows notification dot when there are unsaved preview changes or local overrides
  • Tooltip on gear explains why dot is shown (unsaved changes, device differs from global)
  • Tooltip appears below the button to avoid being cut off
  • Per-setting X buttons to clear individual local overrides, with tooltip showing global value
  • User settings page shows alert when device has local overrides with option to clear them
  • Full-screen reader uses ghost variant button to match other header buttons

Mobile

  • Reader settings accessible via gear icon in bookmark header (when reader mode is active)
  • Settings page uses native sliders for font size and line height
  • Font family selection with checkmark indicator
  • Live preview text updates as settings change
  • "(local)" indicator shown next to settings that have local overrides
  • Options to save as default (all devices), clear local overrides, or clear server defaults

TODO

  • Additional translations (currently English only)

Closes #2198


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/karakeep-app/karakeep/pull/2230 **Author:** [@esimkowitz](https://github.com/esimkowitz) **Created:** 12/7/2025 **Status:** ✅ Merged **Merged:** 12/15/2025 **Merged by:** [@MohamedBassem](https://github.com/MohamedBassem) **Base:** `main` ← **Head:** `reader-text-settings` --- ### 📝 Commits (10+) - [`73707b5`](https://github.com/karakeep-app/karakeep/commit/73707b5f08233b289b476419ffd1f5f5c2fbb3b0) Add initial impl - [`8194c85`](https://github.com/karakeep-app/karakeep/commit/8194c8573864d6578967206666a6ffb772b13dcc) fix some format inconsistencies, add indicator in user settings when local is out of sync - [`e41ef46`](https://github.com/karakeep-app/karakeep/commit/e41ef46fd937806425b6a6ed9468ec63c3b0ebbd) Fix sliders in user settings, unify constants and formatting - [`e5d4916`](https://github.com/karakeep-app/karakeep/commit/e5d4916c27aa6045d34ea4f65bf2ae500347766c) address CodeRabbit suggestions - [`3f144a1`](https://github.com/karakeep-app/karakeep/commit/3f144a182aba9bb2f5c263b0223b940cb43f95d7) add mobile implementation - [`e6ffae9`](https://github.com/karakeep-app/karakeep/commit/e6ffae99f7590162a031ec123f607f42e5540ac4) address coderabbit nitpicks - [`33145df`](https://github.com/karakeep-app/karakeep/commit/33145df0e48f1c17c2a0154073f48fc82dc7c360) fix responsiveness of the reader settings popover - [`c491281`](https://github.com/karakeep-app/karakeep/commit/c4912817809c2fcb5dc788082e09051486e09bf7) Move more of the web UI strings to i18n - [`0743458`](https://github.com/karakeep-app/karakeep/commit/0743458cd4a6857993e1a071a485f4c0003e145b) update translations for more coverage - [`9850e18`](https://github.com/karakeep-app/karakeep/commit/9850e18b6e788fe89fb240ffa7a378675990b725) remove duplicate logic/definitions ### 📊 Changes **30 files changed** (+4866 additions, -199 deletions) <details> <summary>View changed files</summary> 📝 `.gitignore` (+3 -0) 📝 `apps/mobile/app/dashboard/(tabs)/settings.tsx` (+12 -0) 📝 `apps/mobile/app/dashboard/_layout.tsx` (+8 -0) 📝 `apps/mobile/app/dashboard/bookmarks/[slug]/index.tsx` (+20 -7) ➕ `apps/mobile/app/dashboard/settings/reader-settings.tsx` (+264 -0) 📝 `apps/mobile/components/bookmarks/BookmarkLinkPreview.tsx` (+31 -12) 📝 `apps/mobile/components/bookmarks/BookmarkLinkTypeSelector.tsx` (+3 -3) 📝 `apps/mobile/lib/providers.tsx` (+4 -1) ➕ `apps/mobile/lib/readerSettings.tsx` (+93 -0) 📝 `apps/mobile/lib/settings.ts` (+8 -0) 📝 `apps/web/app/dashboard/layout.tsx` (+20 -17) 📝 `apps/web/app/reader/[bookmarkId]/page.tsx` (+12 -128) ➕ `apps/web/app/reader/layout.tsx` (+39 -0) 📝 `apps/web/app/settings/info/page.tsx` (+2 -0) 📝 `apps/web/app/settings/layout.tsx` (+9 -6) 📝 `apps/web/components/dashboard/preview/LinkContentSection.tsx` (+23 -11) ➕ `apps/web/components/dashboard/preview/ReaderSettingsPopover.tsx` (+457 -0) ➕ `apps/web/components/settings/ReaderSettings.tsx` (+288 -0) 📝 `apps/web/lib/i18n/locales/en/translation.json` (+33 -0) ➕ `apps/web/lib/readerSettings.tsx` (+155 -0) _...and 10 more files_ </details> ### 📄 Description ## Reader Text Settings Adds standardized reader text settings with server-side storage for cross-device defaults and client-side local overrides. ### Features - **Three-tier settings precedence**: Session (preview) → Local (device) → Server (global) → Defaults - **Live preview**: Adjust settings in the reader and see changes immediately before saving - **Save options**: - "This device" - saves to localStorage for device-specific preferences - "All devices" - saves to server for cross-device sync - **Per-setting local overrides**: Each setting can be individually overridden on a device, with clear buttons to revert to global defaults - **Settings available in both views**: Full-screen reader and preview pane both have the settings popover - **Flicker-free server sync**: Uses shared pending state to prevent UI flicker when saving to server ### Changes **Shared Logic** - `packages/shared-react/hooks/reader-settings.ts` - New shared hook with core reader settings logic used by both web and mobile: - `pendingServerSave` state prevents UI flicker during server sync - Proper cache invalidation on `onSettled` - Clears local overrides on successful server save - Exposes `isSaving` state - Supports optional session overrides for web live preview **Database & Backend** - `packages/db/schema.ts` - Added `readerFontSize`, `readerLineHeight`, `readerFontFamily` columns to users table - `packages/db/drizzle/0068_add_reader_settings.sql` - Migration for new columns - `packages/shared/types/users.ts` - Added reader settings to zod schemas - `packages/shared/types/readers.ts` - New file with `READER_DEFAULTS`, `READER_FONT_FAMILIES` constants - `packages/trpc/models/users.ts` - Updated getSettings/updateSettings to handle reader settings **Web Frontend** - `apps/web/lib/readerSettings.tsx` - Uses shared hook, adds React Context for session overrides (live preview) - `apps/web/components/dashboard/preview/ReaderSettingsPopover.tsx` - Shared popover component with live preview, +/- buttons for font size and line height, save options, per-setting local override indicators - `apps/web/components/settings/ReaderSettings.tsx` - Settings page component for global defaults with local override warning alert - `apps/web/components/dashboard/preview/LinkContentSection.tsx` - Added settings popover to preview pane - `apps/web/app/reader/[bookmarkId]/page.tsx` - Integrated settings into full-screen reader (ghost variant button) - `apps/web/app/reader/layout.tsx` - New layout with ReaderSettingsProvider - `apps/web/app/dashboard/layout.tsx` - Added ReaderSettingsProvider - `apps/web/app/settings/layout.tsx` - Added ReaderSettingsProvider - `apps/web/lib/i18n/locales/en/translation.json` - Added translation keys **Mobile App** - `apps/mobile/lib/readerSettings.ts` - Uses shared hook with Expo SecureStore adapter, includes mobile-specific font family mappings - `apps/mobile/app/dashboard/settings/reader-settings.tsx` - Full settings page with sliders for font size/line height, font family picker, live preview, and save/clear options - `apps/mobile/app/dashboard/bookmarks/[slug]/index.tsx` - Added settings gear icon in reader header (visible when in reader mode) - `apps/mobile/components/bookmarks/BookmarkLinkPreview.tsx` - Applied reader settings to WebView content (font family, size, line height) - `apps/mobile/app/dashboard/(tabs)/settings.tsx` - Added Reader Settings link in settings tab - `apps/mobile/app/dashboard/_layout.tsx` - Added reader-settings route to navigation stack - `apps/mobile/lib/settings.ts` - Extended local settings type to include reader settings ### UI Details **Web** - Settings gear shows notification dot when there are unsaved preview changes or local overrides - Tooltip on gear explains why dot is shown (unsaved changes, device differs from global) - Tooltip appears below the button to avoid being cut off - Per-setting X buttons to clear individual local overrides, with tooltip showing global value - User settings page shows alert when device has local overrides with option to clear them - Full-screen reader uses ghost variant button to match other header buttons **Mobile** - Reader settings accessible via gear icon in bookmark header (when reader mode is active) - Settings page uses native sliders for font size and line height - Font family selection with checkmark indicator - Live preview text updates as settings change - "(local)" indicator shown next to settings that have local overrides - Options to save as default (all devices), clear local overrides, or clear server defaults ### TODO - [ ] Additional translations (currently English only) Closes #2198 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-02 12:00:16 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/karakeep#2032
No description provided.