feat: squelette de l'extension Read More (config, i18n)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bb8d03eaab
commit
d8b334767d
10 files changed
+193
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
test-results/
|
||||||
|
playwright-report/
|
||||||
|
.omc/
|
||||||
|
.superpowers/
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 vincentb99
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Read More — extension FreshRSS
|
||||||
|
|
||||||
|
Replie les articles du **mode lecture** à une hauteur réduite, avec un bouton
|
||||||
|
**« Lire plus »** qui déroule l'article complet sur place.
|
||||||
|
|
||||||
|
Objectif : parcourir rapidement une liste d'articles (newsletters de veille, sur
|
||||||
|
smartphone notamment) et passer au suivant d'un geste quand le sujet n'intéresse pas.
|
||||||
|
Le passage automatique en « lu » au défilement continue de fonctionner : un article
|
||||||
|
replié est simplement plus court, il est donc marqué lu plus tôt.
|
||||||
|
|
||||||
|
## Prérequis
|
||||||
|
|
||||||
|
- FreshRSS **1.30.4** ou plus récent.
|
||||||
|
- Option FreshRSS *Configuration → Lecture → Marquer un article comme lu… « au défilement de
|
||||||
|
la page »* activée (sinon rien n'est marqué lu au défilement, avec ou
|
||||||
|
sans cette extension).
|
||||||
|
|
||||||
|
## Installation (Docker)
|
||||||
|
|
||||||
|
Le dépôt est directement le dossier de l'extension. Dans le volume monté sur
|
||||||
|
`/var/www/FreshRSS/extensions` :
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker exec -it <conteneur-freshrss> sh -c \
|
||||||
|
'cd /var/www/FreshRSS/extensions && git clone https://git.siteop.biz/vincentb99/freshrss-read-more.git'
|
||||||
|
```
|
||||||
|
|
||||||
|
(ou cloner depuis l'hôte dans le dossier du volume). Puis dans FreshRSS :
|
||||||
|
*Configuration → Extensions → Read More → activer*.
|
||||||
|
|
||||||
|
### Mise à jour
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /var/www/FreshRSS/extensions/freshrss-read-more && git pull
|
||||||
|
```
|
||||||
|
|
||||||
|
puis recharger la page dans le navigateur.
|
||||||
|
|
||||||
|
## Réglage
|
||||||
|
|
||||||
|
Icône engrenage de l'extension : **hauteur repliée** en pixels (250 par défaut, entre
|
||||||
|
100 et 2000). Un article dont le contenu fait moins de 1,5 × cette hauteur n'est pas
|
||||||
|
replié.
|
||||||
|
|
||||||
|
## Comportement
|
||||||
|
|
||||||
|
- Mode lecture uniquement ; vues normale et globale inchangées.
|
||||||
|
- « Lire plus » déplie sur place, sans recharger ni modifier l'état lu/non lu.
|
||||||
|
- Les articles chargés au fil du défilement sont repliés aussi.
|
||||||
|
|
||||||
|
## Développement
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install
|
||||||
|
npm run test:unit # tests unitaires (jsdom)
|
||||||
|
bash tests/e2e/setup.sh # FreshRSS 1.30.4 de test sur http://localhost:8080
|
||||||
|
npx playwright install chromium
|
||||||
|
npm run test:e2e # tests bout-en-bout
|
||||||
|
bash tests/e2e/setup.sh --down # arrêt et nettoyage
|
||||||
|
```
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
MIT
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
/** @var ReadMoreExtension $this */
|
||||||
|
?>
|
||||||
|
<form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post">
|
||||||
|
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="group-name" for="collapsed_height"><?= _t('ext.read_more.height.label') ?></label>
|
||||||
|
<div class="group-controls">
|
||||||
|
<input type="number" id="collapsed_height" name="collapsed_height"
|
||||||
|
value="<?= $this->getCollapsedHeight() ?>"
|
||||||
|
min="<?= ReadMoreExtension::MIN_HEIGHT ?>" max="<?= ReadMoreExtension::MAX_HEIGHT ?>" step="10" />
|
||||||
|
<p class="help"><?= _i('help') ?> <?= _t('ext.read_more.height.help') ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group form-actions">
|
||||||
|
<div class="group-controls">
|
||||||
|
<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
|
||||||
|
<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
final class ReadMoreExtension extends Minz_Extension {
|
||||||
|
public const DEFAULT_HEIGHT = 250;
|
||||||
|
public const MIN_HEIGHT = 100;
|
||||||
|
public const MAX_HEIGHT = 2000;
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function init(): void {
|
||||||
|
$this->registerTranslates();
|
||||||
|
if (!FreshRSS_Context::hasUserConf()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Minz_View::appendStyle($this->getFileUrl('read-more.css'));
|
||||||
|
Minz_View::appendScript($this->getFileUrl('read-more.js'));
|
||||||
|
$this->registerHook(Minz_HookType::JsVars, $this->jsVars(...));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function clampHeight(int $height): int {
|
||||||
|
return max(self::MIN_HEIGHT, min(self::MAX_HEIGHT, $height));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCollapsedHeight(): int {
|
||||||
|
return self::clampHeight($this->getUserConfigurationInt('collapsed_height') ?? self::DEFAULT_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass parameters to read-more.js via `window.context.extensions`.
|
||||||
|
* @param array<mixed> $vars
|
||||||
|
* @return array<mixed>
|
||||||
|
*/
|
||||||
|
public function jsVars(array $vars): array {
|
||||||
|
$vars['read_more'] = [
|
||||||
|
'collapsed_height' => $this->getCollapsedHeight(),
|
||||||
|
'label' => _t('ext.read_more.button'),
|
||||||
|
];
|
||||||
|
return $vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[\Override]
|
||||||
|
public function handleConfigureAction(): void {
|
||||||
|
$this->registerTranslates();
|
||||||
|
if (Minz_Request::isPost()) {
|
||||||
|
$height = Minz_Request::paramInt('collapsed_height') ?: self::DEFAULT_HEIGHT;
|
||||||
|
$this->setUserConfigurationValue('collapsed_height', self::clampHeight($height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'read_more' => [
|
||||||
|
'button' => 'Read more',
|
||||||
|
'height' => [
|
||||||
|
'label' => 'Collapsed height (px)',
|
||||||
|
'help' => 'Visible height of an article before the “Read more” button (100–2000).',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'read_more' => [
|
||||||
|
'button' => 'Lire plus',
|
||||||
|
'height' => [
|
||||||
|
'label' => 'Hauteur repliée (px)',
|
||||||
|
'help' => 'Hauteur visible d’un article avant le bouton « Lire plus » (100 à 2000).',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "Read More",
|
||||||
|
"author": "vincentb99",
|
||||||
|
"description": "Replie les articles du mode lecture avec un bouton « Lire plus »",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"entrypoint": "ReadMore",
|
||||||
|
"type": "user"
|
||||||
|
}
|
||||||
Whitespace-only changes.
Whitespace-only changes.
Reference in new issue
Block a user