* feat(cli): add reconfigure-user.php to read/write per-user config attributes
Closes#8869.
Adds `cli/reconfigure-user.php`, a first-class CLI for per-user configuration attributes — the user-level equivalent of the existing `reconfigure.php` (system config).
### Usage
```sh
# List all attributes (sensitive keys redacted by default)
./cli/reconfigure-user.php --user alice --list
./cli/reconfigure-user.php --user alice --list --show-secrets
# Read a single attribute (exit 2 if key not found)
./cli/reconfigure-user.php --user alice --key language
# Set an attribute (type inferred from existing value: bool, int, string)
./cli/reconfigure-user.php --user alice --key language --set --value fr
# Set from stdin (recommended for secrets — keeps value out of shell history / ps)
./cli/reconfigure-user.php --user alice --key some_token --set --value-stdin < token.txt
# Create a new key, e.g. for an extension (unknown keys rejected by default)
./cli/reconfigure-user.php --user alice --key my_ext_setting --set --value hello --force
# Delete an attribute (exit 2 if key not found)
./cli/reconfigure-user.php --user alice --key some_token --unset
```
### Changes
- `cli/reconfigure-user.php` — new command
- `lib/Minz/Configuration::toArray()` — exposes the full config array (used by `--list`)
- `cli/README.md` — documents the new command
- `tests/cli/UserConfigOptionsParserTest.php` — PHPUnit tests for the options parser, following the existing `CliOptionsParserTest` pattern (shared `cli-parser-test.php` helper)
### Test plan
- `make test-all` passes
- Tested manually against a local FreshRSS instance: `--list`, `--key` (get), `--set` (bool/int/string inference), `--value-stdin`, `--unset`, `--force`, error paths (unknown key without `--force`, wrong type)
* unserialize allowed_classes
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Replace absolute positioning inside `.titleAuthorSummaryDate` with CSS Grid. Title, date, and summary use `grid-area` instead of `position: absolute` + `margin-top: 2.25rem`.
Drops magic numbers that had to stay in sync:
- Three uses of `155px` (date width, title min, title padding) all describing the same column
- `2.25rem` margin-top on summary that had to clear the absolute title
- `90%` summary max-width to keep it off the date
Truncated-title hover-extend now uses `grid-column: 1 / -1` instead of `padding-right: 0.5rem`.
Depends on #8823: grid inside `display: table` mis-sizes in older Gecko, causing summary to misbehave. With the flex base from that PR, the grid sizes correctly in SeaMonkey 2.53.
## Test plan
- `make test-all` passes
- Verified in LibreWolf and SeaMonkey 2.53 with Nord and Origine themes
- Wide, narrow, and mobile viewports
- Toggle combinations: date on/off, summary on/off, hover-extend on truncated titles
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
Convert `.horizontal-list` from `display: table` to `display: flex`. The title item gets `flex: 1; min-width: 0; align-self: stretch` to match the implicit sizing it got from table-cell.
Class name kept so `main.js` `.closest('.horizontal-list')` calls and theme overrides still match. No `gap` or logical properties, so it works back to Firefox 28 / SeaMonkey 2.53.
Prep for #8824 which converts article rows to CSS Grid (#6776). Grid inside `display: table` mis-sizes in older Gecko, so the outer table has to go first.
## Test plan
- `make test-all` passes
- Verified in LibreWolf and SeaMonkey 2.53 with Nord and Origine themes
- Wide, narrow, and mobile viewports
- Bundled themes (Ansum, Origine-compact, Mapco, Swage) checked: no overrides depend on `display: table`
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
* Add a warning message to the API password section, add a log warning when a client uses GET, use POST in sample curl API usage
References #8834.
* Apply suggestion from @Inverle
Co-authored-by: Inverle <inverle@proton.me>
* Apply suggestion from @Inverle (Polish translation)
Co-authored-by: Inverle <inverle@proton.me>
* French translation
* Dutch translation
* German
* Apply suggestion from @Inverle api via post
Co-authored-by: Inverle <inverle@proton.me>
* Apply suggestion from @Inverle via POST (French)
Co-authored-by: Inverle <inverle@proton.me>
* Add user-agent
* update translation info in README
* avoid phpcs line too long
* also trigger on email as suggested by @Inverle
* i18n: fr typography
* make fix-all
---------
Co-authored-by: Inverle <inverle@proton.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
#8839
**Change(s)**
- Fix some typos
- Revise the translations that I hadn't checked before
- Add some new translations
**File(s) changed**
`app/i18n/zh-TW/{admin,conf,gen,sub,user}.php`
`README.md`
`README.fr.md`
Reader view sets .aside.visible { padding-top: 0 } (swage.css:1236), so when
the sidebar is open the absolute-positioned logo lands on the Subscription
management button. Extending the existing hide rule from #8739 to also
cover body.reader is the smallest fix; the logo isn't load-bearing in
reader view. Closes#8802.
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
This keeps the mobile article navigation fixed to the bottom of the viewport by clearing any inherited top offset in the small-screen rule. It updates both LTR and RTL base theme CSS so the previous/next bar remains anchored while browsing on mobile Safari.
Verification: targeted CSS assertion for both base theme files; `git diff --check`.
Closes#8829
Co-authored-by: mzl2233 <mzl2233@users.noreply.github.com>
Reverts #8801 (keeping its incidental blank-line cleanups) and #8815, restoring icon-only feed column on mobile (#8814).
I filed the original PR thinking the icon-only behavior was an inconsistency bug versus the configurable `topline_website` setting, not realizing it was a deliberate mobile choice. The `clamp()` cap helped, but the column still takes space the title could use, and on phones icon-only is the better tradeoff.
A distinct narrow-viewport setting for `topline_website` was raised as a future improvement.
* Revert "fix(themes): cap website column at narrow when feed name is shown (#8815)"
This reverts commit af6a500638.
* Revert "fix(themes): show feed name at narrow widths when configured (#8801)"
This reverts commit 9ff4aec368.
---------
Co-authored-by: FreshRSS Pi <freshrss-pi@localhost>
* docs: add missing app rows to French README
Sync mobile and desktop tables with English README:
add FeedFlow and FluentFlame Reader, previously missing from
the French translation.
* fix(docs): correct Fluent Reader API in French README
Align with English README: Fluent Reader supports the Google Reader
API (preferred), not Fever. The app upstream documents both, and the
English table has long listed GReader.
---------
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
* docs: normalize APIs & native apps table glyphs to monochrome
* docs: use en-dash instead of ✗ for "no" in APIs & native apps table
Per maintainer feedback on #8821: ✗ reads as an error/failure mark; an
en-dash is a neutral "not applicable / no" glyph more appropriate for
a feature-matrix table.
* docs: normalize APIs & native apps table glyphs in French README
Mirror the monochrome-glyph substitutions from README.md:
`✔️` -> `✓`, `➖` -> `–`, `❔` -> `?`, `💲` -> `$`.
---------
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
#8747 (re?)introduced an animation I find unbearably slow. If it was always there I suppose I just got used to it.
How to test the feature manually:
1. Open and close the sidebar on a sufficiently small width.
* feat(import): accept .txt URL lists alongside OPML/JSON/ZIP
Detects .txt by extension and wraps the URL list into a minimal OPML
document so the existing import pipeline handles dedup, categories and
feed limits unchanged. Blank lines, `#` comments and a UTF-8 BOM are
skipped; lines that don't parse as URLs are logged and dropped without
aborting the batch.
Works through both `cli/import-for-user.php` and the web import form.
* utf8BOM
* ENT_COMPAT
---------
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>