diff options
| author | Fuwn <[email protected]> | 2026-02-07 03:26:15 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-07 03:26:15 -0800 |
| commit | f2a5d1c04b9787bbd9f41af699345be6c0345ca8 (patch) | |
| tree | ffbbacd807f0d3d30efb7110058bd70d6404681e /apps/web/app/reader/settings/_components/folders-settings.tsx | |
| parent | style: lowercase all user-facing strings and add custom eslint rule (diff) | |
| download | asa.news-f2a5d1c04b9787bbd9f41af699345be6c0345ca8.tar.xz asa.news-f2a5d1c04b9787bbd9f41af699345be6c0345ca8.zip | |
feat: pre-ship polish — UI improvements, keyboard shortcuts, appearance settings
- Rename "muted keywords" to "muted phrases" throughout settings UI
- Add header with navigation to auth pages (sign-in, sign-up, etc.)
- Merge security tab (TOTP setup) into account settings tab
- Fix TOTP name input truncation on Safari (w-64 → flex-1 min-w-0)
- Add appearance settings: font size, time display format, entry images toggle, reading time toggle
- Add keyboard shortcuts dialog (? key) with all keybindings documented
- Add extended vim shortcuts: gg, G, n/N (next/prev unread), Ctrl+h/l (panel focus)
- Add command palette shortcut (⌘K) to shortcuts dialog
- Add icon URL fields for folders and custom feeds (DB + queries + settings UI)
- Add data-has-unreads attribute for sidebar keyboard navigation
- Fix SSR prerendering crash from Zustand persist and react-resizable-panels localStorage access
- Add detail panel layout persistence via useDefaultLayout
- Update marketing copy to advertise vim-like keyboard navigation
Diffstat (limited to 'apps/web/app/reader/settings/_components/folders-settings.tsx')
| -rw-r--r-- | apps/web/app/reader/settings/_components/folders-settings.tsx | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/apps/web/app/reader/settings/_components/folders-settings.tsx b/apps/web/app/reader/settings/_components/folders-settings.tsx index 8a0012e..2c3d5f2 100644 --- a/apps/web/app/reader/settings/_components/folders-settings.tsx +++ b/apps/web/app/reader/settings/_components/folders-settings.tsx @@ -92,11 +92,13 @@ export function FoldersSettings() { key={folder.folderIdentifier} folderIdentifier={folder.folderIdentifier} name={folder.name} + iconUrl={folder.iconUrl} feedCount={feedCountForFolder(folder.folderIdentifier)} - onRename={(name) => + onSave={(name, iconUrl) => renameFolder.mutate({ folderIdentifier: folder.folderIdentifier, name, + iconUrl, }) } onDelete={() => @@ -115,25 +117,28 @@ export function FoldersSettings() { function FolderRow({ folderIdentifier, name, + iconUrl, feedCount, - onRename, + onSave, onDelete, }: { folderIdentifier: string name: string + iconUrl: string | null feedCount: number - onRename: (name: string) => void + onSave: (name: string, iconUrl: string | null) => void onDelete: () => void }) { const [isEditing, setIsEditing] = useState(false) const [editedName, setEditedName] = useState(name) + const [editedIconUrl, setEditedIconUrl] = useState(iconUrl ?? "") const [showDeleteConfirm, setShowDeleteConfirm] = useState(false) function handleSave() { const trimmedName = editedName.trim() - if (trimmedName && trimmedName !== name) { - onRename(trimmedName) + if (trimmedName) { + onSave(trimmedName, editedIconUrl.trim() || null) } setIsEditing(false) @@ -143,36 +148,51 @@ function FolderRow({ <div className="flex items-center justify-between border-b border-border px-4 py-3 last:border-b-0"> <div className="min-w-0 flex-1"> {isEditing ? ( - <div className="flex items-center gap-2"> + <div className="space-y-2"> + <div className="flex items-center gap-2"> + <input + type="text" + value={editedName} + onChange={(event) => setEditedName(event.target.value)} + className="min-w-0 flex-1 border border-border bg-background-primary px-2 py-1 text-text-primary outline-none focus:border-text-dim" + onKeyDown={(event) => { + if (event.key === "Enter") handleSave() + if (event.key === "Escape") setIsEditing(false) + }} + autoFocus + /> + </div> <input type="text" - value={editedName} - onChange={(event) => setEditedName(event.target.value)} - className="min-w-0 flex-1 border border-border bg-background-primary px-2 py-1 text-text-primary outline-none focus:border-text-dim" - onKeyDown={(event) => { - if (event.key === "Enter") handleSave() - if (event.key === "Escape") setIsEditing(false) - }} - autoFocus + value={editedIconUrl} + onChange={(event) => setEditedIconUrl(event.target.value)} + placeholder="icon url (optional)" + className="w-full border border-border bg-background-primary px-2 py-1 text-text-primary outline-none placeholder:text-text-dim focus:border-text-dim" /> - <button - onClick={handleSave} - className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary" - > - save - </button> - <button - onClick={() => { - setEditedName(name) - setIsEditing(false) - }} - className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary" - > - cancel - </button> + <div className="flex gap-2"> + <button + onClick={handleSave} + className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary" + > + save + </button> + <button + onClick={() => { + setEditedName(name) + setEditedIconUrl(iconUrl ?? "") + setIsEditing(false) + }} + className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary" + > + cancel + </button> + </div> </div> ) : ( <div className="flex items-center gap-2"> + {iconUrl && ( + <img src={iconUrl} alt="" width={16} height={16} className="shrink-0" /> + )} <span className="text-text-primary">{name}</span> <span className="text-text-dim"> ({feedCount} feed{feedCount !== 1 && "s"}) @@ -181,7 +201,7 @@ function FolderRow({ onClick={() => setIsEditing(true)} className="px-2 py-1 text-text-dim transition-colors hover:text-text-secondary" > - rename + edit </button> </div> )} |