7544 Commits

Author SHA1 Message Date
DIYgod 971b003924 fix(desktop): title the follow modal "Add Feed" or "Edit Feed"
Following from a Discover card, a preview or a profile opened a modal
titled "Feeds" or "Edit Feeds", built by joining two words, which also
gave "編集 フィード" in Japanese. It now uses whole phrases: Add Feed,
Edit Feed, Add List and Edit List.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:17:43 +08:00
DIYgod a166648c41 fix(desktop): mark private follow of a list as a paid feature
The list follow and edit form let free users turn on Private Follow, and
the server then rejected the update with "Free user no permission". The
switch is now disabled for free users with the paid badge, as in the
feed form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:16:15 +08:00
DIYgod ff6f71d27a fix(desktop): explain empty Trending lists and category searches
Discover's Trending tab showed an empty card when a language and view
had no trending feeds or the request failed, and a category search
without matches left a blank area under the search box. Trending now
says there are no trending feeds, or shows the error with a Retry
button, and the category search says no results were found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:14:51 +08:00
DIYgod 1146ecb89c fix(desktop): make the undo shortcut readable in light theme toasts
The Cmd+Z badge on the Undo button of the unfollow and mark-all-read
toasts kept the near-white gradient of the kbd style under white text,
so it was invisible in light theme. The badge now drops that gradient.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:10:56 +08:00
DIYgod bfdc2f2034 fix(desktop): let Preview open a list found in Discover
List search results showed a Preview button that was always disabled,
because it only knew how to open a feed. It now opens the list's
timeline, which already previews a list the user does not follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:10:04 +08:00
DIYgod c4bdfa7e04 fix(desktop): count list search results as lists
Searching Discover for lists said "Found 2 feeds" or "No feeds found".
The summary now follows what the search looked for and says "Found 2
lists" or "No lists found".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:08:36 +08:00
DIYgod c44544f481 fix(desktop): show which RSSHub route parameters are missing
Preview with a required route parameter left empty only moved the focus,
because the form never rendered its errors and its inputs were not marked
invalid. Each parameter now shows "This parameter is required." and is
announced as invalid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:06:07 +08:00
DIYgod cb4511a6ad fix(desktop): explain invalid inbox handles, list titles and category names
These forms showed zod's generic messages, such as "Invalid string: must
match pattern /^[a-z0-9_-]+$/" for an inbox handle with a space, and
"Too small: expected string to have >=1 characters" for an empty list
title, category name or Discover search. They now say what to enter, in
every language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:04:02 +08:00
DIYgod c22a7ff600 fix(desktop): list inboxes in the sidebar of the All view
The All view lists the feeds and lists of every view, but its sidebar
left out the Inbox section, which only the Articles view showed. Inboxes
now show in the All view too, where their items already open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:01:22 +08:00
DIYgod 1cdcf90bd8 fix(desktop): name the icon-only buttons of subscriptions and Discover
Screen readers announced a bare "button" for the sidebar sort control and
its options, the category rename save and cancel, the follow "+" on
previewed feeds and lists, the Discover clear results X, the inbox copy
and edit buttons, and the list row and Manage Feeds actions. Each now has
a name, the sort trigger is a focusable button and the sort options say
which one is active.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:00:01 +08:00
DIYgod e476eee358 fix(desktop): trim category names when following or moving feeds
A category of only spaces was saved as is and made a folder with no
name, and "Tech " made a second folder next to "Tech". The follow form
and the New Category dialog now trim the name; the dialog rejects an
empty one and the follow form treats it as no category, like renaming.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:54:27 +08:00
DIYgod 60382ba647 fix(desktop): keep the Discover search box focused when the page loads
Opening /discover directly let the sidebar take focus right after the
search box autofocused. The blur validated the empty box, so it showed
"Too small: expected string to have >=1 characters" before any typing.
The sidebar now takes focus on mount only when nothing else has it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:52:06 +08:00
DIYgod 1f1548bdce fix(desktop): say an OPML file could not be read when parsing fails
A broken OPML file only showed the server's error, which is
"Internal Server Error" or raw parser output. The toast now says the file
could not be read, with the server text below it. Error messages read
through getFetchErrorInfo also drop the request dump the SDK appends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:50:21 +08:00
DIYgod 03cf1cd623 fix(desktop): switch every selected feed to another view
With several feeds selected, Switch to Another View moved only the feed
that was right-clicked, unlike the other items of that menu. It now
moves the whole selection and hides only a view all of them are in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:48:23 +08:00
DIYgod aa1b6cc9e3 fix(desktop): name a renamed feed correctly in the unfollow toast
The toast used the feed's own title rather than the name shown in the
sidebar and read "<feed> have been unfollowed." It now uses the custom
title when there is one, with singular wording in English and French.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:46:51 +08:00
DIYgod 8c65dcabc0 fix(desktop): make undo work after unfollowing a list
Undo sent the list id as a feed id too, and the server answered 404
"Feed not found", so the list stayed unfollowed without any message.
Undo now sends a feed id only for feeds and shows an error toast when
the server rejects it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:45:46 +08:00
DIYgod a35f5aaa75 fix(desktop): keep the custom title when undoing an unfollow
Undo followed the feed again with the feed's own title, so a feed the
user had renamed came back under its original name, and a feed without
a custom title got its current title pinned as one. Undo now sends the
title the subscription had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:43:33 +08:00
DIYgod ddb05b72ab fix(desktop): close only the suggestions when Escape is pressed in a modal combobox
Escape in the Category field of the Add and Edit Feed forms closed the
whole modal and dropped the typed title and category, because Radix
handles Escape on the document first. The modal now stays open while a
combobox shows its suggestions, and the next Escape closes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:42:03 +08:00
DIYgod f7f121cef7 fix(desktop): find the feeds of a website address typed into Discover
Any http(s) address opened the feed preview directly, so a site's home
page such as https://sspai.com always ended in "Error in fetching feed."
Web addresses now go through discovery and list the site's feeds; an
address that is itself a feed still opens its preview.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:40:00 +08:00
DIYgod 4084ec416b fix(desktop): name action exports with the local date and the Folo prefix
The export filename joined the UTC date to the local time, so for some
hours of the day it carried the wrong day next to the local time. Build
both from local time, and use the folo- prefix instead of follow-.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:14:14 +08:00
DIYgod 8021793c7d fix(desktop): translate the subscriber count on profile list cards
The list card footer printed a hard-coded English "subscriber" or
"subscribers" in every language, with "n > 1" as the plural rule. Use the
pluralized feed.follower key that Discover uses for the same count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:13:15 +08:00
DIYgod 4e99f66b58 fix(desktop): show a spinner while actions save and ignore repeat clicks
The round header buttons kept their icon while loading, so a pending save
looked like a disabled Save. Show the spinner instead. A double click could
also start a second save before the pending state reached the button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:11:53 +08:00
DIYgod d6a1b9838f fix(desktop): say why the profile Subscriptions section is empty
The section stayed blank under its heading when there was nothing to show
or the request failed. Show an empty-state line, or an error with Retry.
Feeds without a site link and without a category were also dropped from
the list; group them by the domain of the feed URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:08:55 +08:00
DIYgod d56fd521ff fix(desktop): show a retry in the sidebar when subscriptions fail to load
Without a local sync cursor, a failed subscriptions request left the
sidebar on the "Add more feeds" empty state, as if the user followed
nothing, and nothing retried it. Show an error with Retry instead, except
for guests, who cannot load subscriptions at all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:06:39 +08:00
DIYgod b39fe22a82 fix(desktop): ask signed-out readers to log in instead of showing a network error
Opening an entry URL while signed out, for example right after logging out,
answered 401 and the entry pane said "Network Error" with a Retry that
could never succeed. Show a log-in prompt with a Login button for a 401.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:04:33 +08:00
DIYgod 8f067211ac fix(desktop): flag invalid regex patterns in action conditions
A "Matches Regex" condition with a pattern that does not compile saved
with a success toast, and the rule then never matched. Show the error
under the input and refuse to save while a rule has such a pattern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:02:38 +08:00
DIYgod b01e5a17b4 fix(desktop): fit the settings modal into narrow windows
The panel's 700px minimum width won over its 95vw maximum, so in a window
narrower than about 740px the right side, close button included, was cut
off and could not be scrolled into view. Cap the minimum at 95% of the
viewport.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:59:46 +08:00
DIYgod 4e955c8dbf fix(desktop): label modal close buttons and keep them in tab order
The X of stacked modals and of the shortcuts guide had no accessible name.
The stacked modal X also had tabIndex 1, so Tab jumped out of the dialog
and focus came back to the X, and Cancel and Confirm could not be reached
by tabbing forward.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:57:47 +08:00
DIYgod 7062337024 fix(desktop): name the round header buttons and mark them disabled
GlassButton only showed its description as a tooltip, so Back, New Rule,
Save and the other icon buttons had no accessible name, and a dimmed Save
was still announced as enabled. Use the description as the aria-label and
let callers mark the button aria-disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:56:16 +08:00
DIYgod 92f63cf177 fix(desktop): stop announcing sidebar feeds as disabled buttons
Every feed row got dnd-kit's draggable attributes, which say
aria-disabled=true while nothing is selected, so screen readers announced
each feed as unavailable. Only rows in the multi-selection, the ones that
can be dragged, get those attributes now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:54:48 +08:00
DIYgod 95f5b9db40 fix(store): import exported action rules that have an empty name
The editor saves rules with an empty name and shows "Action N" for them,
but the importer rejected an empty name as missing, so such an export or
clipboard copy could not be imported again. Only reject a missing name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:52:59 +08:00
DIYgod 6f1ab31334 fix(desktop): keep unsaved action edits when the window gets narrow
Below 768px the web app swaps its layout for the download page, which
unmounted the Actions editor and silently discarded unsaved edits. Discard
them when the user confirms leaving instead of on unmount.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:52:25 +08:00
DIYgod 75246b3eb4 fix(desktop): translate the 404 page when it is opened directly
The catch-all route renders outside the app, so on a direct load it
mounted before i18n was set up and showed raw keys such as
errors_page.not_found.description. Render it once the app is ready.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:50:34 +08:00
DIYgod 819d45f138 fix(desktop): wrap the message of confirmation dialogs
whitespace-pre also turns off wrapping and wins over text-wrap in the
Tailwind 4 output, so long ask() messages such as the delete rule warning
were cut off mid-sentence. Use whitespace-pre-line, which keeps line breaks
and wraps, and put the unsaved actions prompt in sentence case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:48:40 +08:00
DIYgod c3eb4e7af8 fix(desktop): name the invalid field when the server rejects a request
Validation failures all carry code 3, so the toast only said "Unprocessable
content" and dropped the server's message that names the field, such as an
invalid webhook URL in an action rule. Show that message as the description,
without the request context the SDK appends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:47:51 +08:00
DIYgod cd933ff923 fix(desktop): keep the action condition value input readable
Since the regex help wrapper was added, the operator select took the whole
condition row and the text value input shrank to about 26px. Give the
wrapper the same flex sizing the bare input had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:45:03 +08:00
DIYgod 2f1c3397b0 fix(desktop): ask again after cancelling the unsaved action changes prompt
Cancelling the prompt left the router blocker blocked, so Back, Escape and
sidebar clicks on the Actions page did nothing and never asked again.
Reset the blocker when the prompt is cancelled or dismissed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:43:04 +08:00
DIYgod 1076922a87 fix(desktop): keep existing action rules when they fail to load
When GET /actions failed on a fresh device, the Actions page showed the
empty state, and saving a new rule there replaced every rule on the server.
Show a load error with Retry instead, and make saveRules refuse to send
rules before the server's rules were loaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:38:53 +08:00
DIYgod 14440a1d29 fix(desktop): open the settings modal for a settings URL instead of a blank page
The /settings routes only describe the settings tabs and their layout
rendered nothing, so a typed or bookmarked settings URL on the web app
was an empty white page. Go to the main view and open the requested tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:48:12 +08:00
DIYgod c294c0761b fix(mobile): ask before the Android back button drops unsaved form edits
Android has no sheet swipe to cancel, and its hardware back button
dismissed a dirty follow, list or RSSHub form at once. Modal groups now
record when their form has unsaved changes, and the back handler asks
with the same prompt the header button and the iOS swipe use, which now
share one helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:07:50 +08:00
DIYgod e8cc67cf17 fix: keep the API message for error codes without a translation
i18next answers a missing key with the key minus its namespace, so the
"t(key) === key" check never matched and an untranslated API code was
shown as a bare number. SDK errors with codes like AUTH_REQUIRED became
"NaN", which is what a signed-out mobile timeline showed. Compare
against the bare code and skip codes that are not numbers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:04:33 +08:00
DIYgod 8b441846a8 fix(desktop): show the feeds the AI guide recommends
The selection screen inserts the recommended feeds in its own mount
effect, which ran before the selected-feeds reader subscribed under
jotai 3, so the list stayed on "No feeds selected yet" while finishing
still followed every hidden feed. Read the selection with
useAtomValueRawSync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:51:05 +08:00
DIYgod 423faf59c1 fix(desktop): enable the mark-all-read shortcut when the app starts in the sidebar
The subscription column focuses its sidebar in a mount effect, which
writes the focus scope in the same commit that mounts the timeline
header. jotai 3 subscribes after that commit, so the header kept the
empty scope and never bound Shift+Cmd+A until focus moved elsewhere.
Read focus scopes with useAtomValueRawSync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:49:52 +08:00
DIYgod 77450d935b fix(ssr): show the signed-in user on the login page
The user provider writes the session user in an effect of the same
commit that mounts the login page's avatar, and jotai 3 subscribes
after that commit, so the avatar kept reading no user and the signed-in
view never showed who was signed in. Read whoami with
useAtomValueRawSync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:48:42 +08:00
DIYgod df282be4ea fix(mobile): show the profile editor's initials avatar in dark mode
The editor painted the initials avatar with the system background to
stand out from the grouped background in light mode, which made it
black on black in dark mode. The fallback avatar now has a fill that
shows on both, so drop the override.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:45:26 +08:00
DIYgod 1deb26010e fix(mobile): keep a long email inside its row on the profile editor
The email text did not shrink, so a long address ran past the card edge
with letters clipped and pushed the verification badge and the chevron
off screen. Let it shrink and truncate in the middle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:45:23 +08:00
DIYgod d6cf0670b2 fix(mobile): say there are no entries yet on an empty timeline
A timeline with nothing in it showed the search message "No results
found." although nothing was searched. Show "No entries yet" instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:43:04 +08:00
DIYgod f9a51f5a92 fix(mobile): describe the badge settings in mobile terms
The appearance settings shared the desktop strings, so iOS and Android
offered to show the unread count "in the dock icon" and described
special badges "in the sidebar". Use app icon and subscription list
wording on mobile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:42:11 +08:00
DIYgod 6bc19c9f46 fix(mobile): keep initials avatars visible on grouped backgrounds
The initials fallback filled its circle with secondary system background,
which is the same color as the grouped background of the Subscriptions
tab, so the header avatar showed bare letters there. Use a translucent
fill that stands out on every background.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:39:19 +08:00
DIYgod ebc18454d7 fix(store): let a fresh feed fetch update follower and update counts
Upserting a feed kept the stored subscriber count, updates per week and
latest entry date whenever one was set, in memory and in SQLite, so the
follow screen and search cards kept showing the first count ever seen.
Keep the stored values only when the incoming feed has none, as feeds
from subscriptions carry no analytics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:36:58 +08:00