diff --git a/locales/fr_FR/LC_MESSAGES/main.mo b/locales/fr_FR/LC_MESSAGES/main.mo index 8749c0f6d..dfa4fe724 100644 Binary files a/locales/fr_FR/LC_MESSAGES/main.mo and b/locales/fr_FR/LC_MESSAGES/main.mo differ diff --git a/locales/fr_FR/LC_MESSAGES/main.po b/locales/fr_FR/LC_MESSAGES/main.po index 841e5a4f2..f9c9fe11a 100644 --- a/locales/fr_FR/LC_MESSAGES/main.po +++ b/locales/fr_FR/LC_MESSAGES/main.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Flus\n" -"POT-Creation-Date: 2026-01-23 17:07+0100\n" -"PO-Revision-Date: 2026-01-23 17:07+0100\n" +"POT-Creation-Date: 2026-02-08 22:00+0100\n" +"PO-Revision-Date: 2026-02-08 22:00+0100\n" "Last-Translator: Marien Fressinaud \n" "Language-Team: \n" "Language: fr_FR\n" @@ -280,10 +280,12 @@ msgid "The name must be less than {max} characters." msgstr "Le nom ne doit pas faire plus de {max} caractères." #: models/Collection.php:139 models/Collection.php:229 +#: navigations/ReadingNavigation.php:27 msgid "Bookmarks" msgstr "Signets" #: models/Collection.php:150 models/Collection.php:231 +#: navigations/ReadingNavigation.php:34 msgid "Links read" msgstr "Liens lus" @@ -292,6 +294,7 @@ msgid "Links never to read" msgstr "Liens à ne jamais lire" #: models/Collection.php:172 models/Collection.php:233 +#: navigations/ReadingNavigation.php:20 msgid "News" msgstr "Journal" @@ -347,6 +350,54 @@ msgstr "Le nom d’utilisateur·ice ne doit pas contenir le caractère ‘@’." msgid "The password is required." msgstr "Le mot de passe est obligatoire." +#: navigations/AccountNavigation.php:26 +msgid "Overview" +msgstr "Aperçu" + +#: navigations/AccountNavigation.php:34 +msgid "Account validation" +msgstr "Validation du compte" + +#: navigations/AccountNavigation.php:43 +msgid "Mastodon" +msgstr "Mastodon" + +#: navigations/AccountNavigation.php:52 +msgid "OPML import" +msgstr "Importation OPML" + +#: navigations/AccountNavigation.php:60 +msgid "Data export" +msgstr "Exportation des données" + +#: navigations/AccountNavigation.php:67 +msgid "Credentials" +msgstr "Identifiants" + +#: navigations/AccountNavigation.php:74 +msgid "Sessions" +msgstr "Sessions" + +#: navigations/AccountNavigation.php:81 +msgid "Account deletion" +msgstr "Suppression du compte" + +#: navigations/AccountNavigation.php:85 +msgid "Account" +msgstr "Compte" + +#: navigations/AccountNavigation.php:86 +msgid "Data" +msgstr "Données" + +#: navigations/AccountNavigation.php:87 +msgid "Security" +msgstr "Sécurité" + +#: navigations/ReadingNavigation.php:41 +msgid "Explore" +msgstr "Explorer" + #: seeds.php:15 msgid "Business" msgstr "Business" @@ -977,12 +1028,6 @@ msgstr "" "Quoiqu’il en soit, cette erreur n’est pas de votre fait et vous n’avez plus " "qu’à revenir en arrière." -#: views/explore/disabled.html.twig:3 views/explore/disabled.html.twig:17 -#: views/explore/disabled.html.twig:21 -#: views/layouts/_reading_navigation.html.twig:37 -msgid "Explore" -msgstr "Explorer" - #: views/explore/disabled.html.twig:24 msgid "Exploration is disabled as administrator did not setup topics." msgstr "" @@ -1149,54 +1194,6 @@ msgstr "Ok !" msgid "Import a file" msgstr "Importer un fichier" -#: views/layouts/_account_navigation.html.twig:5 -msgid "Account" -msgstr "Compte" - -#: views/layouts/_account_navigation.html.twig:13 -msgid "Overview" -msgstr "Aperçu" - -#: views/layouts/_account_navigation.html.twig:23 -#: views/my/validation/new.html.twig:3 views/my/validation/new.html.twig:12 -#: views/my/validation/show.html.twig:3 views/my/validation/show.html.twig:16 -msgid "Account validation" -msgstr "Validation du compte" - -#: views/layouts/_account_navigation.html.twig:34 -msgid "Mastodon" -msgstr "Mastodon" - -#: views/layouts/_account_navigation.html.twig:40 -msgid "Data" -msgstr "Données" - -#: views/layouts/_account_navigation.html.twig:49 -msgid "OPML import" -msgstr "Importation OPML" - -#: views/layouts/_account_navigation.html.twig:59 -msgid "Data export" -msgstr "Exportation des données" - -#: views/layouts/_account_navigation.html.twig:64 -msgid "Security" -msgstr "Sécurité" - -#: views/layouts/_account_navigation.html.twig:72 -#: views/my/security/show.html.twig:3 views/my/security/show.html.twig:15 -msgid "Credentials" -msgstr "Identifiants" - -#: views/layouts/_account_navigation.html.twig:81 -msgid "Sessions" -msgstr "Sessions" - -#: views/layouts/_account_navigation.html.twig:90 -#: views/my/account/deletion.html.twig:3 views/my/account/deletion.html.twig:16 -msgid "Account deletion" -msgstr "Suppression du compte" - #: views/layouts/_header-connected.html.twig:7 #: views/layouts/_header-disconnected.html.twig:4 #, php-format @@ -1268,7 +1265,7 @@ msgstr "Se déconnecter" msgid "Language" msgstr "Langue" -#: views/layouts/_modal_dialog.html.twig:22 views/layouts/sidenav.html.twig:24 +#: views/layouts/_modal_dialog.html.twig:22 views/layouts/_sidenav.html.twig:24 msgid "Close" msgstr "Fermer" @@ -1305,6 +1302,10 @@ msgstr "Rechercher des liens par mots ou URL" msgid "Search" msgstr "Rechercher" +#: views/layouts/_sidenav.html.twig:10 +msgid "Navigation" +msgstr "Navigation" + #: views/layouts/_title.html.twig:6 msgid "Error: " msgstr "Erreur : " @@ -1328,10 +1329,6 @@ msgstr "Accéder au contenu principal" msgid "About %s" msgstr "À propos de %s" -#: views/layouts/sidenav.html.twig:10 -msgid "Navigation" -msgstr "Navigation" - #: views/links/_link.html.twig:63 msgid "This link seems to be inaccessible, you should repair it." msgstr "Ce lien semble inaccessible, vous devriez le réparer." @@ -2714,9 +2711,3 @@ msgstr "Recommencer l’introduction" #: views/support/show.html.twig:117 msgid "What’s new?" msgstr "Quoi de neuf ?" - -#~ msgid "See notes by" -#~ msgstr "Voir les notes de" - -#~ msgid "About" -#~ msgstr "À propos" diff --git a/public/static/icons.svg b/public/static/icons.svg index 4c599ed28..84fb48781 100644 --- a/public/static/icons.svg +++ b/public/static/icons.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/src/Application.php b/src/Application.php index 7a959fffb..8ed86ec06 100644 --- a/src/Application.php +++ b/src/Application.php @@ -51,6 +51,7 @@ public function __construct() \Minz\Template\Twig::addAttributeExtension(twig\FormattersExtension::class); \Minz\Template\Twig::addAttributeExtension(twig\IconExtension::class); \Minz\Template\Twig::addAttributeExtension(twig\LocaleExtension::class); + \Minz\Template\Twig::addAttributeExtension(twig\NavigationExtension::class); \Minz\Template\Twig::addAttributeExtension(twig\UrlExtension::class); } diff --git a/src/assets/stylesheets/layouts/sidenav.css b/src/assets/stylesheets/layouts/sidenav.css index 3df9a809e..7b1a0aacc 100644 --- a/src/assets/stylesheets/layouts/sidenav.css +++ b/src/assets/stylesheets/layouts/sidenav.css @@ -85,10 +85,6 @@ transition: background-color 0.2s ease-in-out; } -.sidenav__menu-item--bold { - font-weight: 600; -} - .sidenav__menu-item:hover, .sidenav__menu-item:focus { background-color: rgb(0 0 0 / 5%); diff --git a/src/navigations/AccountNavigation.php b/src/navigations/AccountNavigation.php new file mode 100644 index 000000000..bfc0cf9ef --- /dev/null +++ b/src/navigations/AccountNavigation.php @@ -0,0 +1,90 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class AccountNavigation extends BaseNavigation +{ + public function elements(): array + { + $current_user = CurrentUser::require(); + + $account_items = []; + $data_items = []; + $security_items = []; + + $account_items[] = new Item( + 'account', + \Minz\Url::for('account'), + 'cog', + TwigExtension::translate('Overview'), + ); + + if (!$current_user->isValidated()) { + $account_items[] = new Item( + 'account validation', + \Minz\Url::for('account validation'), + 'check', + TwigExtension::translate('Account validation'), + ); + } + + if (!$current_user->isBlocked()) { + $account_items[] = new Item( + 'mastodon', + \Minz\Url::for('mastodon'), + 'mastodon', + TwigExtension::translate('Mastodon'), + ); + } + + if (!$current_user->isBlocked()) { + $data_items[] = new Item( + 'opml', + \Minz\Url::for('opml'), + 'upload', + TwigExtension::translate('OPML import'), + ); + } + + $data_items[] = new Item( + 'exportation', + \Minz\Url::for('exportation'), + 'backup', + TwigExtension::translate('Data export'), + ); + + $security_items[] = new Item( + 'security', + \Minz\Url::for('security'), + 'key', + TwigExtension::translate('Credentials'), + ); + + $security_items[] = new Item( + 'sessions', + \Minz\Url::for('sessions'), + 'connect', + TwigExtension::translate('Sessions'), + ); + + $security_items[] = new Item( + 'account deletion', + \Minz\Url::for('account deletion'), + 'trash', + TwigExtension::translate('Account deletion'), + ); + + return [ + new ItemGroup(TwigExtension::translate('Account'), $account_items), + new ItemGroup(TwigExtension::translate('Data'), $data_items), + new ItemGroup(TwigExtension::translate('Security'), $security_items), + ]; + } +} diff --git a/src/navigations/BaseNavigation.php b/src/navigations/BaseNavigation.php new file mode 100644 index 000000000..c5fa25aeb --- /dev/null +++ b/src/navigations/BaseNavigation.php @@ -0,0 +1,45 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +abstract class BaseNavigation +{ + public function __construct( + private string $current, + ) { + } + + public function currentLabel(): string + { + $items = []; + foreach ($this->elements() as $element) { + if ($element instanceof ItemGroup) { + $items = array_merge($items, $element->items); + } elseif ($element instanceof Item) { + $items[] = $element; + } + } + + foreach ($items as $item) { + if ($this->isCurrent($item)) { + return $item->label; + } + } + + return ''; + } + + public function isCurrent(Item $item): bool + { + return $item->key === $this->current; + } + + /** + * @return Element[] + */ + abstract public function elements(): array; +} diff --git a/src/navigations/Element.php b/src/navigations/Element.php new file mode 100644 index 000000000..550605ea1 --- /dev/null +++ b/src/navigations/Element.php @@ -0,0 +1,12 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +abstract class Element +{ + abstract public function is(string $type): bool; +} diff --git a/src/navigations/Item.php b/src/navigations/Item.php new file mode 100644 index 000000000..582dca2ac --- /dev/null +++ b/src/navigations/Item.php @@ -0,0 +1,23 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class Item extends Element +{ + public function __construct( + public readonly string $key, + public readonly string $url, + public readonly string $icon, + public readonly string $label, + ) { + } + + public function is(string $type): bool + { + return $type === 'item'; + } +} diff --git a/src/navigations/ItemGroup.php b/src/navigations/ItemGroup.php new file mode 100644 index 000000000..a291bc085 --- /dev/null +++ b/src/navigations/ItemGroup.php @@ -0,0 +1,22 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class ItemGroup extends Element +{ + public function __construct( + public readonly string $label, + /** @var Item[] */ + public readonly array $items, + ) { + } + + public function is(string $type): bool + { + return $type === 'group'; + } +} diff --git a/src/navigations/ReadingNavigation.php b/src/navigations/ReadingNavigation.php new file mode 100644 index 000000000..a571e62f5 --- /dev/null +++ b/src/navigations/ReadingNavigation.php @@ -0,0 +1,45 @@ + + * @license http://www.gnu.org/licenses/agpl-3.0.en.html AGPL + */ +class ReadingNavigation extends BaseNavigation +{ + public function elements(): array + { + return [ + new Item( + 'news', + \Minz\Url::for('news'), + 'reading', + TwigExtension::translate('News'), + ), + + new Item( + 'bookmarks', + \Minz\Url::for('bookmarks'), + 'bookmark', + TwigExtension::translate('Bookmarks'), + ), + + new Item( + 'read', + \Minz\Url::for('read list'), + 'check', + TwigExtension::translate('Links read'), + ), + + new Item( + 'explore', + \Minz\Url::for('explore'), + 'compass', + TwigExtension::translate('Explore'), + ), + ]; + } +} diff --git a/src/twig/NavigationExtension.php b/src/twig/NavigationExtension.php new file mode 100644 index 000000000..cc6401a2d --- /dev/null +++ b/src/twig/NavigationExtension.php @@ -0,0 +1,21 @@ + -

{{ t('Account') }}

- - - {{ icon('cog') }} - {{ t('Overview') }} - - - {% if not app.user.isValidated %} - - {{ icon('check') }} - {{ t('Account validation') }} - - {% endif %} - - {% if not app.user.isBlocked %} - - {{ icon('mastodon') }} - {{ t('Mastodon') }} - - {% endif %} - - -
-

{{ t('Data') }}

- - {% if not app.user.isBlocked %} - - {{ icon('upload') }} - {{ t('OPML import') }} - - {% endif %} - - - {{ icon('backup') }} - {{ t('Data export') }} - -
- -
-

{{ t('Security') }}

- - - {{ icon('key') }} - {{ t('Credentials') }} - - - - {{ icon('connect') }} - {{ t('Sessions') }} - - - - {{ icon('trash') }} - {{ t('Account deletion') }} - -
-{% endblock %} diff --git a/src/views/layouts/_reading_navigation.html.twig b/src/views/layouts/_reading_navigation.html.twig deleted file mode 100644 index 3cd563033..000000000 --- a/src/views/layouts/_reading_navigation.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -{% extends 'layouts/sidenav.html.twig' %} - -{% block body %} - - {{ icon('reading') }} - {{ t('News') }} - - - - {{ icon('bookmark') }} - {{ t('Bookmarks') }} - - - - {{ icon('check') }} - {{ t('Links read') }} - - - - {{ icon('compass') }} - {{ t('Explore') }} - -{% endblock %} diff --git a/src/views/layouts/sidenav.html.twig b/src/views/layouts/_sidenav.html.twig similarity index 80% rename from src/views/layouts/sidenav.html.twig rename to src/views/layouts/_sidenav.html.twig index b1e183df2..d3a39f212 100644 --- a/src/views/layouts/sidenav.html.twig +++ b/src/views/layouts/_sidenav.html.twig @@ -6,7 +6,7 @@ data-sidenav-target="opener" aria-expanded="false" > - {{ icon('angle-double', 'rotate90') }} + {{ icon('bars') }} {{ t('Navigation') }} @@ -19,15 +19,16 @@ data-action="sidenav#close" data-sidenav-target="closer" > - {{ icon('angle-double', 'rotate270') }} + {{ icon('times') }} {{ t('Close') }} - {% block body %} - {% endblock %} + {% for element in navigation.elements %} + {{ include('layouts/_sidenav_element.html.twig') }} + {% endfor %} diff --git a/src/views/layouts/_sidenav_element.html.twig b/src/views/layouts/_sidenav_element.html.twig new file mode 100644 index 000000000..26f8ea3e4 --- /dev/null +++ b/src/views/layouts/_sidenav_element.html.twig @@ -0,0 +1,18 @@ +{% if element.is('group') %} +
+

{{ element.label }}

+ + {% for item in element.items %} + {{ include('layouts/_sidenav_element.html.twig', { element: item }) }} + {% endfor %} +
+{% else %} + + {{ icon(element.icon) }} + {{ element.label }} + +{% endif %} diff --git a/src/views/mastodon/authorization.html.twig b/src/views/mastodon/authorization.html.twig index 11ad7f3e5..b3cc389a9 100644 --- a/src/views/mastodon/authorization.html.twig +++ b/src/views/mastodon/authorization.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'mastodon' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'mastodon') }) }} {% endblock %} {% block body %} diff --git a/src/views/mastodon/show.html.twig b/src/views/mastodon/show.html.twig index a75a9ca89..f03ba29a3 100644 --- a/src/views/mastodon/show.html.twig +++ b/src/views/mastodon/show.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'mastodon' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'mastodon') }) }} {% endblock %} {% block body %} diff --git a/src/views/my/account/deletion.html.twig b/src/views/my/account/deletion.html.twig index 2bd322953..105ac47fe 100644 --- a/src/views/my/account/deletion.html.twig +++ b/src/views/my/account/deletion.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'account deletion' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'account deletion') }) }} {% endblock %} {% block body %} diff --git a/src/views/my/account/show.html.twig b/src/views/my/account/show.html.twig index 1ea9f1ca8..6e7243dd6 100644 --- a/src/views/my/account/show.html.twig +++ b/src/views/my/account/show.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'account' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'account') }) }} {% endblock %} {% block body %} diff --git a/src/views/my/security/confirmation.html.twig b/src/views/my/security/confirmation.html.twig index c95c5675b..8eb50fc76 100644 --- a/src/views/my/security/confirmation.html.twig +++ b/src/views/my/security/confirmation.html.twig @@ -9,14 +9,14 @@ {% block navigation %} {% if form.isRedirectingTo('sessions') %} - {% set page = 'sessions' %} + {% set current = 'sessions' %} {% elseif form.isRedirectingTo('security') %} - {% set page = 'security' %} + {% set current = 'security' %} {% else %} - {% set page = '' %} + {% set current = '' %} {% endif %} - {{ include('layouts/_account_navigation.html.twig', { page: page }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: current) }) }} {% endblock %} {% block body %} diff --git a/src/views/my/security/show.html.twig b/src/views/my/security/show.html.twig index 00bf85871..38e0b383f 100644 --- a/src/views/my/security/show.html.twig +++ b/src/views/my/security/show.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'security' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'security') }) }} {% endblock %} {% block body %} diff --git a/src/views/my/sessions/index.html.twig b/src/views/my/sessions/index.html.twig index 25a7c1886..2c5d8a01c 100644 --- a/src/views/my/sessions/index.html.twig +++ b/src/views/my/sessions/index.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'sessions' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'sessions') }) }} {% endblock %} {% block body %} diff --git a/src/views/my/validation/show.html.twig b/src/views/my/validation/show.html.twig index dbdd1b802..3ade2594f 100644 --- a/src/views/my/validation/show.html.twig +++ b/src/views/my/validation/show.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_account_navigation.html.twig', { page: 'account validation' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: account_navigation(current: 'account validation') }) }} {% endblock %} {% block body %} diff --git a/src/views/news/index.html.twig b/src/views/news/index.html.twig index f6a21a47f..2bbfc4987 100644 --- a/src/views/news/index.html.twig +++ b/src/views/news/index.html.twig @@ -8,7 +8,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_reading_navigation.html.twig', { page: 'news' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: reading_navigation(current: 'news') }) }} {% endblock %} {% block back %} diff --git a/src/views/read/index.html.twig b/src/views/read/index.html.twig index 371428773..d03ce8650 100644 --- a/src/views/read/index.html.twig +++ b/src/views/read/index.html.twig @@ -14,7 +14,7 @@ {% endblock %} {% block navigation %} - {{ include('layouts/_reading_navigation.html.twig', { page: 'read' }) }} + {{ include('layouts/_sidenav.html.twig', { navigation: reading_navigation(current: 'read') }) }} {% endblock %} {% block back %}