340 Commits
Author SHA1 Message Date
DIYgodandClaude Opus 5.5 3eca68c9d4 feat(mobile): add previous and next entry buttons to the reader
Readers can step through the entries of a list from the reader instead of
scrolling to the end of each entry or going back to the list.

- An up/down control floats at the bottom of the reader: liquid glass on
  iOS 26+, a blur on older iOS and an elevated surface on Android, above
  the floating player bar while it shows.
- Entries swap in place, so the screen pushed from the list keeps its
  back gesture and the control stays under the thumb. Pulling up past the
  end does the same instead of replacing the screen with a fade.
- The list hands the reader its loaded entries and loads its next page
  when the reader nears the last one; the next entry's content loads
  ahead.
- The control slides away with the header when "Hide Header While
  Reading" is on, and while pulling up to the next entry.
- Going back shows the entry read last below the list header. FlashList
  adds viewOffset to the scroll position, so the old +70 hid it.

There is no horizontal swipe: on iOS 26 swiping right anywhere in the
content goes back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:32:42 +08:00
DIYgodandClaude Opus 5.5 b3c041a12d Merge branch 'dev' into claude/code-review-e2e-testing-923ae1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:42:23 +08:00
DIYgodandClaude Opus 5.5 c2df550ab9 fix(desktop): show a chosen RSSHub instance as the fallback it now is
The server fetches RSSHub feeds from Folo's built-in instance first and uses the instance a user
chose only when that fails. The page says so, keeps the built-in one marked In Use, marks the
chosen one Fallback and offers "Use as Fallback" and "Use Only This" instead of "Use".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 07:47:54 +08:00
DIYgodandClaude Opus 5.5 d73bf69d76 fix(desktop): check an RSSHub instance address as the server does before saving it
POST /rsshub now refuses an address that is not http(s) or has credentials, a query or a
fragment, answering only "Unprocessable content". The form says what is wrong first, and still
saves an instance edited with the address it was stored with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 07:47:54 +08:00
DIYgodandClaude Opus 5.5 8a9b49ef98 fix: say that a verified account approves an email change from its current email
The server now sends the approval link to the current address; the new one gets its link after
that. Desktop and mobile say so for verified accounts, and the store no longer shows the new
address before the change is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 07:09:44 +08:00
DIYgodandClaude Opus 5.5 dcfd1fa359 fix(mobile): tell Google Play users when the Play Store is unavailable
On a device without a usable Play Store, for example with no Google
account signed in, the billing connection opens but every query fails.
The plan screen showed no purchase buttons without saying why, and
Restore Purchases surfaced the billing library's English error.

When Play products cannot load, the plan screen now explains that Google
Play is unavailable, and Restore Purchases and upgrades report the same
localized message when owned purchases cannot be read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:13:16 +08:00
DIYgodandClaude Opus 5.5 e51f39e11d feat(mobile): sell subscriptions through Google Play Billing on Play installs
Google Play found the Android app leading users to Stripe Checkout, which
its Payments policy forbids for apps it distributes. Android installs from
Google Play now buy, restore and manage subscriptions through Google Play
Billing only; the GitHub APK keeps Stripe, and iOS keeps the App Store.

- getMobileBillingProvider() picks the App Store, Google Play or Stripe.
  An unknown installer counts as Google Play, so Stripe needs a known
  non-Play installer.
- GooglePlayBillingProvider (expo-iap) loads the Play products listed in
  PAYMENT_PLAN_LIST, buys the eligible offer (the free trial when Play
  offers one, else the base plan) with the user's account token as the
  obfuscated account ID, has the server verify and acknowledge the
  purchase through /billing/google/verify, then acknowledges it locally.
  Upgrades replace the current Play subscription with time proration.
  Unacknowledged and pending purchases are synced once the store
  connects, and Restore Purchases verifies every owned subscription.
- The plan screen shows Play prices and free trial length, opens the Play
  subscription center to manage, and never offers Stripe or another
  store's subscription on a Play install; a subscription bought
  elsewhere shows a neutral hint instead.
- Only the provider for this install's store is mounted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:13:16 +08:00
DIYgodandClaude Opus 5.5 e792c3b87a fix(profile): take new handles of A-Z, a-z, 0-9 and _ only on both apps
Mobile refused only spaces and invisible characters in a new or changed handle,
unlike desktop and the server's new rule. Both now take letters A-Z, digits and
underscores up to 36, keep an unchanged legacy handle saving, and map HANDLE_INVALID.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:39:58 +08:00
DIYgodandClaude Opus 5.5 c3e2e8f013 fix(actions): stop overwriting action rules changed elsewhere
A save now sends the version of the rules it started from as expectedUpdatedAt,
so the server answers 409 instead of replacing another device's changes.
Desktop and mobile then offer to load the latest rules, keep editing, or save over them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 04:13:33 +08:00
DIYgodandClaude Opus 5.5 850714d788 fix(mobile): name what the handle check refuses in its message
Edit Profile refuses only spaces and invisible characters in a new handle,
as the server does, yet said "Use only letters, numbers and underscores."
from desktop's stricter check, although dots, dashes and CJK handles save.
It now says what it refuses, in every locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:57:18 +08:00
DIYgodandClaude Opus 5.5 4d370c5b8c fix(mobile): explain Spotlight and let its empty list add a rule
With no rules, Spotlight showed "Add rule" as gray text that did nothing,
and the footer repeated "Add rule" even when rules existed. The empty list
now has an "Add rule" button, and the footer says what Spotlight
highlights and which rule wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:48:32 +08:00
DIYgodandClaude Opus 5.5 0f2e744a37 fix(desktop): quote "Show Unread Only" as the settings show it
The English "Hide read" description quoted "Show unread only", while the
setting it refers to is shown title-cased as "Show Unread Only". The other
languages already quote their labels as shown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:01:17 +08:00
DIYgodandClaude Opus 5.5 9daf2e66d3 fix(desktop): say where Spotlight highlights apply
The new Spotlight description said rules only color the entry list, but
they also color the text of an opened entry and AI summaries. The copy
now names all three in every language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:29:14 +08:00
DIYgodandClaude Opus 5.5 c692b02e8f fix(desktop): tidy small text and layout slips in Settings
The list delete warning ended in "!.." in English, Japanese and French.
The Thumbnail Ratio select sat 8px below its label because of a leftover
offset and a malformed class. In a narrow Feeds table the date column
kept its 150px and cut names to one letter; below 640px it now gives its
space to the names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:11:55 +08:00
DIYgodandClaude Opus 5.5 32e714cf49 fix(desktop): explain Spotlight rules and how the web gets notifications
The Spotlight tab was a lone "Add rule" button with no word on what a
rule does. It now says that rules highlight words or patterns in the
entry list and that the higher rule wins, and shows "No rules yet."
On the web, the empty Notifications list now says to add an Action with
"Notification of New Entry", reload and allow browser notifications.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:04:05 +08:00
DIYgodandClaude Opus 5.5 6001533621 fix(desktop): name the unnamed buttons and switches in Settings
Screen readers met nameless controls in Preferences: the AI shortcut,
MCP and task edit buttons and switches, Enable MCP Services and Enable
BYOK, the BYOK provider and email edit buttons, and two auth buttons both
called "Link". They now carry names such as "Edit shortcut", the item
name, "Change Email" and "Link Google".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:49:45 +08:00
DIYgodandClaude Opus 5.5 af3b784d82 fix(desktop): replace zod's developer wording in form errors
Account, password and 2FA forms showed messages such as "Invalid string:
must match pattern /^\w+$/" or "Too small: expected string to have >=8
characters", in every language. Common text checks now say "This field
is required.", "Use at least 8 characters." and the like, translated,
and the handle and TOTP code get their own messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:46:13 +08:00
DIYgodandClaude Opus 5.5 8f676504e0 fix(desktop): say that "Hide read" works with "Show unread only"
"Hide read" only hides read subscriptions while the unread-only filter is
on, so turning it on in the default view seemed to do nothing. Its
description now says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:09:16 +08:00
DIYgodandClaude Opus 5.5 c3d82a6132 fix(desktop): describe "Unread only on launch" as the unread filter it is
The setting is the same remembered filter the timeline header button
switches, so a quick "Show all" in the header turned the "on launch"
preference off. It is now called "Show unread only" and says that the
header button changes it and that the choice is kept for the next launch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:09:00 +08:00
DIYgodandClaude Opus 5.5 a785dccf79 fix(desktop): say when a handle is already taken
Saving a handle another user has failed with a bare "Internal Server
Error" toast, because the server lets the unique index reject it. After
a failed save the form now looks the handle up and, when someone else
has it, marks the Handle field with "This handle is already taken."

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:04:38 +08:00
DIYgodandClaude Opus 5.5 908c1ec687 fix(desktop): stop reporting an unverified email change as done
For an unverified account the Change Email form said "Email changed." and
showed the new address, but the server only sends a link to it and keeps
the old email until that link is opened. The form now says the
verification email was sent, closes, and leaves the shown email alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:56:32 +08:00
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 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
DIYgodandClaude Opus 5.5 10c98ed809 fix(desktop): name the accent color swatches for screen readers
The accent color swatches and the custom color button were icon-only
buttons without a label or selected state, so screen readers announced
nine unnamed buttons. Each now has its color name and aria-pressed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:21:04 +08:00
DIYgodandClaude Opus 5.5 0594fea3a1 fix(desktop): apply the proxy setting on blur and report invalid values
Every keystroke in the proxy field was sent to the main process, which
reset the session proxy and created a new undici agent for each partial
value, and an invalid value (such as "127.0.0.1:7890" without a scheme)
was silently dropped while the field kept showing it. The field now
applies on blur or Enter, treats a host and port without a scheme as an
HTTP proxy, shows an error when the main process rejects the value, and
then displays the proxy that was actually stored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:09:34 +08:00
DIYgodandClaude Opus 5.5 324ba75114 fix(desktop): confirm before deleting a custom integration
The delete icon next to edit and pause removed the custom integration,
with its URL template and headers, at once and without undo. MCP
services and BYOK providers in the same settings ask first; custom
integrations now ask too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:03:12 +08:00
DIYgodandClaude Opus 5.5 ce7a100677 feat(desktop): offer the 2FA setup key for authenticators that can't scan
Enabling two-factor authentication only showed a QR code. An
authenticator on the same computer, such as a password manager, cannot
scan it, and there was no way to get the key. A "Copy setup key"
button under the code now copies the TOTP secret.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 01:54:59 +08:00
DIYgodandClaude Opus 5.5 9949ddeabb fix(desktop): give each autocomplete input its own accessible name
The shared Autocomplete always set aria-label "Select Category", which
was wrong for the feed search in the list settings. Callers now pass a
label that matches their purpose. The list search reuses
lists.select_feeds, whose zh-CN copy drops a stray period and zh-TW
copy uses the Taiwan word for "current".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:52:12 +08:00
DIYgodandClaude Opus 5.5 9e51f06c69 refactor(desktop): remove dead integration, discover and AI settings code
Nothing imports CustomIntegrationValidator, DiscoverForm (replaced by
UnifiedDiscoverForm), TimelinePromptSection (taken off the AI settings
page in 691307925) or AiOnboardingModal. URLSchemeHandler.getExamples,
the CustomIntegrationManager validate helpers, formatFileSize and
withDisplayStateHandler have no callers. Remove them along with the
locale keys only they used.

The aiTimelinePrompt setting stays because the server still reads it
when it scores the AI timeline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:51:16 +08:00
DIYgodandClaude Opus 5.5 9603533ed4 fix(i18n): translate hard-coded UI strings and complete every locale
Move the hard-coded English left in the desktop renderer, the Electron
main process, the mobile app and the shared packages to i18next, with
en, zh-CN, zh-TW, ja and fr-FR translations. SSR share pages are
unchanged.

- Fill every namespace in every language, delete keys no code reads
  (server error codes stay) and update translations left behind by
  later English changes.
- Stop HTML-escaping interpolated values in the desktop renderer.
  React already escapes text, so names with & or quotes showed entities.
- Render error boundary fallbacks as components so they can use hooks.
- Localize zod validation messages with the app language.
- Throw ClipboardError from the clipboard helpers and show translated
  toasts. formatEstimatedMins takes a formatter so callers localize the
  units.
- Use one glossary term per concept in ja, fr-FR and zh-TW.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:50:23 +08:00
DIYgodandClaude Opus 5.5 a7216df5d4 fix(i18n): translate the remaining zh-TW strings
Add every zh-TW key missing from settings and mobile, which fell back to
Simplified Chinese, and translate the values still in English: wallet
transaction labels, social link placeholders, and English words inside
translated strings (Proxy, Fetch, Authenticator, issue, token, App).
Brand names, acronyms and terms that zh-CN also keeps in English stay
as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:03:45 +08:00
DIYgodandClaude Opus 5.5 da7b60ab15 fix(desktop): bundle the zh-CN and zh-TW AI locales in Electron
Electron never loads locales at runtime: every language is bundled in
default-resource.electron.ts. The ai namespace of zh-CN and zh-TW still
pointed at the English placeholder added before those translations
existed, so the AI settings and chat panel stayed in English.

- Import the real ai locale files, and test the Electron map against
  locales/ for every supported language and namespace.
- Skip the localStorage locale cache in Electron and start i18next in the
  user's language. Only builds from before June 2025 wrote that cache and
  nothing refreshes it, so it could only shadow the bundled resources.
- Translate the zh-TW plan settings titles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:20:36 +08:00
DIYgodandClaude Opus 5.5 a9e6b72642 fix(i18n): correct the zh-TW hide read subscriptions label
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 00:04:33 +08:00
Sangeeth Thilakarathnaandsanmaxdev 489019f62e docs: add regex help for action conditions (#5036)
Co-authored-by: sanmaxdev <sanmaxdev@users.noreply.github.com>
2026-09-26 22:22:44 +08:00
DIYgodandClaude Fable 5.1 93b83f95eb feat(mobile): add reading settings, manual theme and immersive header
- add a Reading settings screen (content font, line height, text color,
  inline style, code theme) reachable from Appearance and from the entry
  "more" menu
- add a System / Light / Dark theme setting applied through
  Appearance.setColorScheme so the reader WebView follows it as well
- optionally slide the entry header away while scrolling down and keep a
  blurred status bar strip so the clock stays readable
- forward reader typography to the html renderer through a new
  setReaderStyle bridge call

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 12:50:51 +08:00
KomhandClaude Sonnet 5 44f0e5df06 fix(tray): Linux tray icon duplicates and dead menus on minimize-to-tray toggle (#5086)
On Linux, `Tray.destroy()` does not remove the icon from StatusNotifierItem
hosts (waybar, KDE Plasma), so toggling "Minimize to tray" off and on stacked a
dead icon every time. Keep the single Tray instance for the app's lifetime
instead; the window close handler reads `getTrayConfig()` live, so a tray icon
that outlives a disabled setting is inert.

The icon cannot be removed from a running process, so `setTrayConfig` reports
when a restart is needed and the renderer offers one via a new `app.relaunch`
IPC. That relaunch runs from `$APPIMAGE` where set (AppImage's `execPath` points
into a mount that is gone by then), drops `--start-in-tray` so it never comes
back hidden, and uses `app.quit()` so `before-quit` still persists the window
bounds and flushes cookies.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 18:10:14 +08:00
DIYgod dbab1121fa fix(mobile): add subscription legal links 2026-09-03 18:54:32 +08:00
DIYgod e1daec3013 feat(power): restrict power usage to wallet 2026-04-30 14:23:23 +08:00
DIYgod ad1cf02cd7 feat(mobile): add streaming tts playback 2026-04-10 20:44:09 +08:00
DIYgod f6cdb64186 feat: add spotlight settings across desktop and mobile 2026-04-09 13:45:05 +08:00
waitandClaude Opus 4.6 bd879d5f9e fix: resolve Obsidian EPERM on macOS by using native folder picker (#4242) (#4924)
- Replace text input with native dialog.showOpenDialog for vault path selection
- Add path validity detection with three-state UI (unselected/valid/invalid)
- Fix YAML frontmatter parsing failure with Chinese/special characters
- Fix ENOENT error when vault subdirectory doesn't exist
- Add AI summary (description) to Obsidian frontmatter export
- Add author fallback to feed title when entry author is empty
- Increase filename truncation limit from 20 to 80 characters for CJK titles

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 20:57:21 +08:00
DIYgod d27261d76e fix(mobile): simplify iOS subscription management (#4947) 2026-04-02 07:27:21 +00:00
DIYgod fa7ce0f011 fix(cli): use npx latest and restore login flow 2026-03-17 12:18:24 +08:00
DIYgod 9a8280ded4 feat(cli): switch desktop sync to folocli 2026-03-17 11:18:48 +08:00
DIYgod aea75fe57b fix(desktop): improve self-test coverage and ui polish 2026-03-13 10:20:01 +08:00
DIYgod df83cf62ea fix(mobile): polish auth and settings ux 2026-03-13 10:15:33 +08:00