feat: Introduce the Shaarli Professional theme with new templates, styles, scripts, and updated documentation.

This commit is contained in:
Bruno Charest 2026-02-11 16:37:44 -05:00
parent 5d486d3d97
commit 70ebda3079
9 changed files with 405 additions and 171 deletions

317
README.md
View File

@ -1,55 +1,204 @@
# Shaarli BC Theme (Professional)
# Shaarli Professional Theme
> Thème moderne pour [Shaarli](https://github.com/shaarli/Shaarli), pensé pour une expérience professionnelle, responsive et compatible modes clair/sombre.
> Thème moderne et professionnel pour [Shaarli](https://github.com/shaarli/Shaarli), pensé pour une expérience utilisateur premium, responsive et performante.
## Présentation
- **Nom interne :** Professional
- **Version :** 1.0.0
- **Auteur :** Antigravity
- **Dossier :** `tpl/shaarli-pro`
| | |
|---|---|
| **Nom interne** | Professional (`shaarli-pro`) |
| **Version** | 1.0.0 |
| **Compatibilité** | Shaarli ≥ 0.9, PHP ≥ 7.4 |
| **Licence** | MIT |
| **Dossier** | `tpl/shaarli-pro` |
Le thème fournit un layout type application avec barre latérale fixe, navigation fluide, focus sur laccessibilité et une couche JavaScript dédiée aux interactions.
Le thème offre un layout de type application avec barre latérale fixe, navigation fluide, mode clair/sombre natif, et une couche JavaScript riche dédiée à l'interactivité.
## Fonctionnalités principales
---
1. **Mode clair/sombre natif** avec mémorisation du choix utilisateur.
2. **Sidebar intelligente** : navigation compacte sur desktop, menu escamotable sur mobile.
3. **Recherche “Spotlight”** en surimpression : raccourci `S`, navigation au clavier, surlignage des résultats.
4. **Filtres rapides** pour isoler liens publics, privés ou non tagués.
5. **Variables CSS centralisées** pour personnaliser palette, ombres, typographies.
## Fonctionnalités
## Compatibilité et prérequis
### 🎨 Design & Interface
- Shaarli ≥ 0.9 (sélection du thème depuis *Tools > Configure your Shaarli*).
- Accès en écriture au répertoire `tpl/`.
- Possibilité de modifier `data/config.json.php` pour les installations plus anciennes.
- **Mode clair / sombre** avec bascule instantanée, mémorisation dans `localStorage`, et support de `prefers-color-scheme` du système.
- **Anti-FOUC** : un script inline dans `<head>` applique le thème *avant* le chargement du CSS pour éviter le flash de contenu non stylé.
- **Variables CSS centralisées** (`--primary`, `--bg-body`, `--text-main`, etc.) pour une personnalisation aisée de la palette, des ombres et de la typographie.
- **Police Inter** (Google Fonts) pour une typographie moderne et lisible.
- **Icônes Material Design Icons** (MDI Webfont v7.2) pour une iconographie cohérente et riche.
- **Animations fluides** : transitions sur les cartes, menus, modales, filtres, et effets de hover.
### 📐 Layout Sidebar + Header
- **Sidebar fixe** sur desktop (230px) avec :
- Logo et titre de l'instance
- Navigation : Bookmarks, Tag Cloud, Picture Wall, Daily
- Section Admin (si connecté) : Tools, Settings
- Bouton « New Bookmark » (si connecté)
- Toggle clair/sombre intégré
- **Header sticky** avec :
- Navigation principale (HOME, TAG CLOUD, PICTURE WALL, DAILY, SEARCH)
- Actions rapides : filtres, multi-sélection, RSS, outils, login/logout
- Support des boutons de plugins (`plugins_header.buttons_toolbar`)
- **Responsive** : la sidebar se transforme en menu escamotable (hamburger) sous 1024px.
### 🔍 Recherche « Spotlight »
- Modale de recherche en surimpression inspirée de macOS Spotlight.
- **Raccourci clavier** : touche `S` pour ouvrir, `ESC` pour fermer.
- **Deux modes** : recherche par texte libre ou filtrage par tags.
- **Résultats en temps réel** avec défilement au clavier (↑ / ↓) et sélection via `Enter`.
- **Surlignage** (highlight) des termes correspondants dans les résultats.
- **Debounce** (150ms) pour optimiser les performances lors de la saisie.
### 🎛️ Filtres Rapides
- **Panneau de filtres** en dropdown depuis le header :
- Nombre de liens par page (20, 50, 100, ou valeur personnalisée)
- Filtrage par visibilité : liens privés, publics, ou tous (si connecté)
- Filtrage par tags : liens non tagués uniquement
- **Bannière d'information** dynamique indiquant les filtres actifs avec compteur de résultats.
- **Indicateur visuel** (badge pulsant) sur le bouton filtre lorsque des filtres sont actifs.
- **Bouton "Clear"** pour réinitialiser tous les filtres en un clic.
### 📄 Trois Vues de Liens
| Vue | Description |
|-----|-------------|
| **Grille** | Cartes avec miniatures, description tronquée (3 lignes), tags et actions. Idéal pour le parcours visuel. |
| **Liste** | Disposition horizontale avec miniature latérale en fondu, description (2 lignes), footer avec tags et actions. |
| **Compact** | Mode dense style tableau : titre + URL sur une ligne, tags et actions alignés à droite. Parfait pour les grandes collections. |
- Le choix de vue est persisté dans `localStorage`.
- Chaque vue a son propre positionnement pour : badges de visibilité, cases de sélection, boutons d'action.
### ✅ Multi-Sélection & Actions Groupées
- **Mode sélection** activable via le bouton dans le header.
- Cases à cocher sur chaque bookmark (apparaissent au survol ou en mode sélection).
- **Barre d'actions groupées** fixe en bas avec :
- Compteur de sélection
- « Select all » pour sélectionner tous les liens visibles
- Actions : DELETE, SET PUBLIC, SET PRIVATE
- Bouton CANCEL pour quitter le mode
### 🖼️ Picture Wall (Mur d'Images)
- **Grille responsive** avec taille d'image configurable via un slider (120px400px).
- **Boutons +/** pour ajuster rapidement la taille.
- **Persistance** de la taille choisie dans `localStorage`.
- **Overlay au survol** avec titre et URL du bookmark.
- **Animations** : zoom léger de l'image au survol, apparition de l'overlay en slide.
- **Indicateur de lien externe** (icône en haut à droite au survol).
### 📅 Page Daily
- Navigation jour / semaine / mois avec boutons de sélection.
- Affichage chronologique des bookmarks avec :
- Titre cliquable vers l'URL originale
- Miniature (si disponible)
- Description formatée
- Horodatage et tags
- Navigation précédent / suivant entre les périodes.
- Support des zones de plugins.
### 🎵 Lecteur Multimédia Persistant
- **Détection automatique** des URLs audio/streaming dans les bookmarks.
- Bouton ▶ injecté dans la barre d'actions des bookmarks contenant des médias.
- **Barre de lecture fixe** en bas de page avec :
- Lecture / Pause
- Barre de progression interactive
- Affichage du temps (ou « LIVE » pour les flux en continu)
- Contrôle de volume avec bouton mute
- Bouton de fermeture
- **Persistance entre pages** : le lecteur reprend la lecture au même point lors de la navigation.
- Formats supportés : MP3, OGG, FLAC, WAV, AAC, M4A, OPUS, WMA, WEBM, M3U8, M3U, PLS.
### 🔌 Intégration des Plugins
- **QR Code** : remplacement de l'image inline par une icône MDI + modale élégante avec animation.
- **ReadItLater** :
- Icônes MDI (œil ouvert/fermé) au lieu du texte brut
- Badge « To Read » positionné sur les bookmarks non lus
- Bordure rouge sur les bookmarks à lire
- Masquage du bouton « Mark as Read » dans la zone de pagination
- **Zones de plugins** : toutes les zones Shaarli standard sont supportées (`plugin_start_zone`, `plugin_end_zone`, `link_plugin`, `edit_link_plugin`, `buttons_toolbar`, etc.).
### 📄 Pages d'Administration
- **Outils** : liste moderne avec icônes, labels, sous-labels et chevrons de navigation.
- **Configuration** : formulaires stylés avec le design system du thème.
- **Gestion des tags** : renommage et suppression avec interface claire.
- **Import / Export** : pages de gestion des bookmarks Netscape.
- **Plugins Admin** : configuration et activation/désactivation des plugins.
- **Statistiques** : affichage du nombre total de liens et liens privés.
- **Bookmarklets** : boutons « Shaare link » et « Add Note » prêts à glisser.
- **Apps tierces** : liens rapides vers les extensions Firefox, Chrome, et apps Android/iOS.
### ♿ Accessibilité & Performance
- `:focus-visible` pour les éléments interactifs (clavier uniquement).
- `content-visibility: auto` sur les cartes de bookmarks pour un rendu optimisé.
- `loading="lazy"` sur les images et miniatures.
- Support `@media print` : masquage automatique de la sidebar, header et actions.
- Markup sémantique HTML5.
- Attributs `title` sur tous les boutons et liens d'action.
### 📱 Responsive Design
| Breakpoint | Adaptations |
|------------|-------------|
| `> 1024px` | Layout complet sidebar + contenu |
| `≤ 1024px` | Sidebar escamotable, menu mobile, textes de nav masqués |
| `≤ 768px` | Grille en colonne unique, toolbar empilé, header nav masqué |
| `≤ 480px` | Paddings réduits, vue liste en colonne, miniatures pleine largeur |
---
## Installation
1. **Télécharger** ce dépôt ou récupérer uniquement `shaarli-pro/` via la page des releases.
### 1. Téléchargement
```bash
git clone https://git.dracodev.net/Projets/Shaarli_bm_theme.git
git clone https://github.com/votre-utilisateur/shaarli_bc_theme.git
```
2. **Copier** le dossier `shaarli-pro/` dans `tpl/` à côté du dossier `default/`.
### 2. Copie dans Shaarli
Copier le dossier `shaarli-pro/` dans le répertoire `tpl/` de votre instance Shaarli, à côté du dossier `default/` :
```bash
docker cp "./shaarli-pro" myshaarli:/var/www/shaarli/tpl/
# Via Docker
docker cp "./shaarli-pro" shaarli_bookmarks:/var/www/shaarli/tpl/
# Ou manuellement
cp -r shaarli-pro/ /path/to/shaarli/tpl/
```
3. **Vérifier les droits** (lecture par lutilisateur du serveur web).
### 3. Permissions
```bash
docker exec -it myshaarli chown -R www-data:www-data /var/www/shaarli/tpl/
# Docker
docker exec -it shaarli_bookmarks chown -R nginx:nginx /var/www/shaarli/tpl/shaarli-pro
# Manuel
chown -R www-data:www-data /path/to/shaarli/tpl/shaarli-pro/
```
---
## Activation
### Via linterface (recommandé)
1. Connectez-vous à Shaarli en tant quadministrateur.
### Via l'interface (recommandé)
1. Connectez-vous à Shaarli en tant qu'administrateur.
2. Ouvrez **Tools > Configure your Shaarli**.
3. Choisissez **Professional (shaarli-pro)** dans la liste des thèmes.
4. Sauvegardez, puis rafraîchissez la page daccueil.
4. Sauvegardez, puis rafraîchissez la page d'accueil.
### Activation manuelle (Shaarli < 0.9)
Ajoutez ou mettez à jour `data/config.json.php` :
Modifiez `data/config.json.php` :
```json
{
@ -58,35 +207,115 @@ Ajoutez ou mettez à jour `data/config.json.php` :
}
}
```
ou utiliser cette commande docker
Ou via Docker :
```bash
docker exec -it myshaarli sed -i 's/"theme": "default"/"theme": "shaarli-pro"/' /var/www/shaarli/data/config.json.php
```
Redémarrez votre service PHP si nécessaire et videz le cache navigateur.
Redémarrez PHP si nécessaire et videz le cache navigateur.
## Configuration & personnalisation
---
- **Palette et typographies** : modifiez les variables dans `shaarli-pro/css/style.css` ou surchargez-les proprement via `data/user.css`.
- **Comportements front** : adaptez `shaarli-pro/js/script.js` (toggle thème, recherche, filtres, sidebar).
- **CSS/JS personnalisés** : placez vos ajouts dans `data/user.css` ou créez un template additionnel (`extra.html`) pour de futurs scripts.
## Configuration & Personnalisation
## Structure utile
### Palette et Typographies
- `shaarli-pro/css/style.css` : styles principaux et variables.
- `shaarli-pro/js/script.js` : interactions (mode sombre, recherche, filtres, sidebar mobile).
- `shaarli-pro/*.html` : templates RainTPL couvrant toutes les vues Shaarli.
- `example_Shaarli-Material/` : thème hérité servant dexemple/sandbox.
Modifiez les variables CSS dans `shaarli-pro/css/style.css` section `:root` et `[data-theme="dark"]`, ou surchargez-les proprement via `data/user.css` :
## Mise à jour
```css
/* data/user.css */
:root {
--primary: #8b5cf6; /* Violet au lieu de bleu */
--primary-hover: #7c3aed;
--bg-body: #fafaf9;
}
```
1. Sauvegardez vos données (`data/`) et vos surcharges.
### Comportements JavaScript
Adaptez `shaarli-pro/js/script.js` pour personnaliser :
- Le mode de recherche par défaut (tags vs texte)
- Les extensions audio reconnues par le lecteur
- Le comportement des filtres
### Templates additionnels
Créez un fichier `tpl/shaarli-pro/extra.html` pour injecter du CSS/JS supplémentaire — il sera automatiquement inclus s'il existe.
---
## Structure du Projet
```
shaarli-pro/
├── css/
│ └── style.css # Styles principaux + variables CSS (light/dark)
├── js/
│ └── script.js # Interactions (thème, recherche, filtres, sélection, lecteur)
├── theme_info.php # Métadonnées du thème
├── includes.html # Head commun (meta, CSS, JS, config Shaarli)
├── page.header.html # Sidebar + Header + Search overlay + Filtres
├── page.footer.html # Footer + Bulk actions bar + Media player
├── linklist.html # Page principale des bookmarks
├── linklist.paging.html # Composant de pagination
├── daily.html # Vue quotidienne / hebdomadaire / mensuelle
├── editlink.html # Formulaire d'ajout/édition de bookmark
├── picwall.html # Mur d'images avec contrôle de taille
├── tag.cloud.html # Nuage de tags avec filtre alphabétique
├── tag.list.html # Liste de tags avec recherche dynamique
├── tag.sort.html # Navigation entre vues tag
├── tools.html # Page d'administration
├── loginform.html # Formulaire de connexion
├── configure.html # Page de configuration
├── changepassword.html # Changement de mot de passe
├── changetag.html # Gestion des tags
├── pluginsadmin.html # Administration des plugins
├── server.html # Informations serveur
├── server.requirements.html # Prérequis serveur
├── import.html # Import de bookmarks
├── export.html # Export de bookmarks
├── export.bookmarks.html # Template d'export Netscape
├── addlink.html # Ajout rapide de lien
├── editlink.batch.html # Édition par lot
├── thumbnails.html # Synchronisation des miniatures
├── opensearch.html # Descripteur OpenSearch
├── feed.rss.html # Template de flux RSS
├── feed.atom.html # Template de flux Atom
├── dailyrss.html # Template RSS quotidien
├── 404.html # Page d'erreur 404
├── error.html # Page d'erreur générique
└── page.html # Page wrapper
```
---
## Raccourcis Clavier
| Touche | Action |
|--------|--------|
| `S` | Ouvrir la recherche Spotlight |
| `ESC` | Fermer la recherche / les filtres / les modales |
| `↑` / `↓` | Naviguer dans les résultats de recherche |
| `Enter` | Sélectionner le résultat courant |
---
## Mise à Jour
1. Sauvegardez vos personnalisations (`data/user.css`, `extra.html`).
2. Remplacez le dossier `tpl/shaarli-pro/` par la nouvelle version.
3. Purgez les caches navigateur/OPcache.
3. Purgez les caches navigateur et OPcache.
4. Vérifiez le bon fonctionnement de vos plugins.
---
## Support
- Ouvrez une issue GitHub en joignant captures et logs.
- Indiquez vos versions (Shaarli, thème, plugins activés) pour faciliter le diagnostic.
- Ouvrez une issue en joignant captures d'écran et logs.
- Indiquez vos versions : Shaarli, PHP, thème et plugins activés.
Bon partage de liens !
---
Bon partage de liens ! 🔖

View File

@ -2387,9 +2387,6 @@ select:focus {
box-shadow: var(--shadow-sm);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.picwall-pictureframe {
will-change: transform;
}
@ -2450,7 +2447,6 @@ select:focus {
}
.picwall-title {
display: block;
font-size: 0.95rem;
font-weight: 600;
color: white;
@ -3669,3 +3665,82 @@ select:focus {
display: none;
}
}
/* ===== Footer ===== */
.footer-main {
margin-top: 3rem;
padding: 2rem 0;
border-top: 1px solid var(--border);
text-align: center;
color: var(--text-secondary);
font-size: 0.9rem;
}
.footer-main a {
color: var(--text-main);
transition: color 0.2s ease;
}
.footer-main a:hover {
color: var(--primary);
}
.footer-feeds {
margin-top: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.25rem;
}
.footer-separator {
margin: 0 0.5rem;
color: var(--text-muted);
}
.plugin-footer-text {
margin-top: 0.5rem;
}
/* ===== Tools Page ===== */
.page-tools .list-sortable-handle {
cursor: pointer;
padding: 0;
margin-right: 1rem;
display: flex;
align-items: center;
}
.page-tools .list-sortable-handle i {
font-size: 1.5rem;
color: var(--primary);
}
.page-tools .list-group-item>i {
color: var(--text-muted);
flex-shrink: 0;
}
.bookmarklet-actions {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.third-party-links {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
}
.third-party-links .btn i {
font-size: 1.2rem;
}
/* Utility */
.text-right {
text-align: right;
}

View File

@ -77,12 +77,12 @@
{if="!$hide_timestamps || $is_logged_in"}
<a href="{$base_path}/shaare/{$value.shorturl}" class="daily-item-footer-subtitle" title="{'Permalink'|t}">
{if="$type === 'week'"}
{function="strftime('%a %e %b, %H:%M', $link.timestamp)"}
{function="date('D j M, H:i', $link.timestamp)"}
{else}
{if="$type === 'month'"}
{function="strftime('%a %e %b %Y, %H:%M', $link.timestamp)"}
{function="date('D j M Y, H:i', $link.timestamp)"}
{else}
{function="strftime('%H:%M', $link.timestamp)"}
{function="date('H:i', $link.timestamp)"}
{/if}
{/if}
</a>

View File

@ -40,13 +40,13 @@
<div class="form-group">
<label class="form-label" for="lf_title{$index}">{'Title'|t}</label>
<div class="{$asyncLoadClass}">
<input type="text" class="form-control" name="lf_title" id="lf_title{$index}" {if="empty($batch_mode) && $link.title==''"}class="autofocus form-control"{else}class="form-control"{/if} value="{$link.title}" placeholder="Page title">
<input type="text" class="form-control{if="empty($batch_mode) && $link.title==''"} autofocus{/if}" name="lf_title" id="lf_title{$index}" value="{$link.title}" placeholder="Page title">
</div>
</div>
<div class="form-group">
<label class="form-label" for="lf_description{$index}">{'Description'|t}</label>
<div class="{$asyncLoadClass}">
<textarea class="form-control" name="lf_description" id="lf_description{$index}" {if="empty($batch_mode) && $link.description==''"}class="autofocus form-control"{/if} placeholder="Add a description..." rows="5">{$link.description}</textarea>
<textarea class="form-control{if="empty($batch_mode) && $link.description==''"} autofocus{/if}" name="lf_description" id="lf_description{$index}" placeholder="Add a description..." rows="5">{$link.description}</textarea>
</div>
{if="$formatter==='markdown'"}
<div class="sublabel">

View File

@ -1140,31 +1140,20 @@ document.addEventListener('DOMContentLoaded', () => {
'.mp3', '.mp4', '.ogg', '.webm', '.m3u8', '.flac', '.wav', '.aac',
'.m4a', '.opus', '.wma', '.oga', '.m3u', '.pls'
];
const STREAM_PATTERNS = [
'icecast', 'shoutcast', 'stream', 'radio', 'listen', 'audio',
'/live', '.stream'
];
function isMediaUrl(url) {
if (!url) return false;
const lower = url.toLowerCase();
// Check file extensions
// Strip query params and fragment for cleaner extension matching
const pathname = lower.split('?')[0].split('#')[0];
// Check file extensions at end of path
for (const ext of MEDIA_EXTENSIONS) {
if (lower.includes(ext)) return true;
if (pathname.endsWith(ext)) return true;
}
// Check streaming patterns
for (const pattern of STREAM_PATTERNS) {
if (lower.includes(pattern) && (lower.includes('http') || lower.includes('//'))) {
// Must also look like an audio/stream URL (not just any page about audio)
if (lower.endsWith('.mp3') || lower.endsWith('.ogg') || lower.endsWith('.m3u8') ||
lower.endsWith('.aac') || lower.endsWith('.flac') || lower.endsWith('.m4a') ||
lower.endsWith('.wav') || lower.endsWith('.opus') || lower.endsWith('.pls') ||
lower.endsWith('.m3u') || lower.includes('.mp3') || lower.includes('.ogg') ||
lower.includes('stream') || lower.includes('icecast') || lower.includes('listen')) {
// Check streaming URL patterns (path-segment matching)
if (/\/(stream|listen|live|icecast|shoutcast)(\/|$|\?)/i.test(url)) {
return true;
}
}
}
return false;
}

View File

@ -57,7 +57,7 @@
</a>
<span class="link-url">{$value.url}</span>
<div class="link-meta">
<span class="link-date">{function="strftime('%c', $value.timestamp)"}</span>
<span class="link-date">{$value.created|format_date}</span>
<a href="{$base_path}/shaare/{$value.shorturl}" class="link-permalink" title="Permalink"><i class="mdi mdi-link-variant"></i></a>
</div>
</div>

View File

@ -1,55 +0,0 @@
<!DOCTYPE html>
<html{if="$language !== 'auto'"} lang="{$language}"{/if}>
<head>
{$pageName="linklist"}
{include="includes"}
</head>
<body>
{include="page.header"}
<div id="linklist">
{loop="$plugin_start_zone"}
{$value}
{/loop}
<!-- Toolbar with View Toggle -->
<div class="content-toolbar">
<div class="toolbar-left">
{include="linklist.paging"}
</div>
<div class="toolbar-right">
<div class="view-toggle">
<button class="view-toggle-btn active" id="view-grid-btn" title="Grid View">
<i class="mdi mdi-view-grid"></i>
</button>
<button class="view-toggle-btn" id="view-list-btn" title="List View">
<i class="mdi mdi-view-list"></i>
</button>
<button class="view-toggle-btn" id="view-compact-btn" title="Compact View">
<i class="mdi mdi-view-headline"></i>
</button>
</div>
</div>
</div>
{if="count($links)==0"}
<div class="empty-state">
<div class="empty-state-icon">
<i class="mdi mdi-bookmark-off-outline"></i>
</div>
<h2 class="empty-state-title">No bookmarks found</h2>
<p class="empty-state-text">
{if="!empty($search_term)"}
No results for: <strong>{$search_term}</strong>
{else}
Start adding bookmarks to see them here.
{/if}
</p>
</div>
{else}
<div class="links-list view-grid" id="links-list">
{loop="$links"}
<div id="{$value.id}" class="link-outer{if="isset($value.sticky) && $value.sticky"} is-sticky{/if}{if="$value.class"} {$value.class}{/if}{if="$value.private"} private{else} public{/if}" data-id="{$value.id}">

View File

@ -1,15 +1,15 @@
<footer class="footer-main" style="margin-top: 3rem; padding: 2rem 0; border-top: 1px solid var(--border); text-align: center; color: var(--text-secondary); font-size: 0.9rem;">
<footer class="footer-main">
<p>
Powered by <a href="https://github.com/shaarli/Shaarli" target="_blank" rel="noopener" style="color:var(--text-main);">Shaarli</a>.
Powered by <a href="https://github.com/shaarli/Shaarli" target="_blank" rel="noopener">Shaarli</a>.
{if="$is_logged_in"}
<span class="footer-divider">|</span> <a href="{$base_path}/admin/tools" style="color:var(--text-main);">Administration</a>
<span class="footer-separator">|</span> <a href="{$base_path}/admin/tools">Administration</a>
{/if}
</p>
<div class="footer-feeds" style="margin-top: 0.5rem;">
<div class="footer-feeds">
<a href="{$base_path}/feed/rss" title="RSS Feed"><i class="mdi mdi-rss"></i> RSS</a>
<span style="margin: 0 0.5rem;"></span>
<span class="footer-separator"></span>
<a href="{$base_path}/feed/atom" title="Atom Feed">Atom</a>
<span style="margin: 0 0.5rem;"></span>
<span class="footer-separator"></span>
<a href="{$base_path}/daily" title="Daily">Daily</a>
</div>

View File

@ -15,76 +15,76 @@
<div class="card-header">{'Settings'|t}</div>
<div class="list-group">
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/configure">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-cog" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-cog"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Configure your Shaarli'|t}</div>
<div class="list-group-item-sublabel">{'Change Title, timezone...'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
{if="!$openshaarli"}
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/password">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-lock" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-lock"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Change password'|t}</div>
<div class="list-group-item-sublabel">{'Change your password'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
{/if}
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/plugins">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-puzzle" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-puzzle"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Plugin administration'|t}</div>
<div class="list-group-item-sublabel">{'Enable, disable and configure plugins'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/server">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-server" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-server"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Server administration'|t}</div>
<div class="list-group-item-sublabel">{'Check instance\'s server configuration'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/tags">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-tag-multiple" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-tag-multiple"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Manage Tags'|t}</div>
<div class="list-group-item-sublabel">{'Rename or delete a tag in all links'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/import">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-file-import" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-file-import"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Import'|t}</div>
<div class="list-group-item-sublabel">{'Import Netscape html bookmarks'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
<a class="list-group-item list-group-item-action ripple" href="{$base_path}/admin/export">
<div class="list-sortable-handle" style="cursor: pointer; padding: 0; margin-right: 1rem;">
<i class="mdi mdi-file-export" style="font-size: 1.5rem; color: var(--primary);"></i>
<div class="list-sortable-handle">
<i class="mdi mdi-file-export"></i>
</div>
<div class="list-group-item-content">
<div class="list-group-item-label">{'Export'|t}</div>
<div class="list-group-item-sublabel">{'Export Netscape html bookmarks'|t}</div>
</div>
<i class="mdi mdi-chevron-right" style="color: var(--text-muted);"></i>
<i class="mdi mdi-chevron-right"></i>
</a>
</div>
</div>
@ -136,13 +136,10 @@
<p class="text-muted" style="margin-bottom: 1.5rem;">
Drag these buttons to your bookmarks bar to quickly add links from any page.
</p>
<div class="row" style="display: flex; gap: 1rem; justify-content: center;">
<div class="col-xs-6 text-center">
<div class="bookmarklet-actions">
<a class="btn btn-primary" href="javascript:(function(){var%20url%20=%20location.href;var%20title%20=%20document.title%20||%20url;var%20desc=document.getSelection().toString();if(desc.length>4000){desc=desc.substr(0,4000)+'...';alert('{function="str_replace(' ', '%20', t('The selected text is too long, it will be truncated.'))"}');}window.open('{$pageabsaddr}admin/shaare?post='%20+%20encodeURIComponent(url)+'&amp;title='%20+%20encodeURIComponent(title)+'&amp;description='%20+%20encodeURIComponent(desc)+'&amp;source=bookmarklet','_blank','menubar=no,height=800,width=600,toolbar=no,scrollbars=yes,status=no,dialog=1');})();">
<i class="mdi mdi-bookmark-plus"></i> {'Shaare link'|t}
</a>
</div>
<div class="col-xs-6 text-center">
<a class="btn btn-secondary" href="javascript:(function(){var desc=document.getSelection().toString();if(desc.length>4000){desc=desc.substr(0,4000)+'...';alert('{function="str_replace(' ', '%20', t('The selected text is too long, it will be truncated.'))"}');}window.open('{$pageabsaddr}?private=1&amp;post='+'&amp;description='%20+%20encodeURIComponent(desc)+'&amp;source=bookmarklet','_blank','menubar=no,height=800,width=600,toolbar=no,scrollbars=yes,status=no,dialog=1');})();">
<i class="mdi mdi-note-plus"></i> {'Add Note'|t}
</a>
@ -151,28 +148,27 @@
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="card">
<div class="card-header">{'3rd party'|t}</div>
<div class="card-body">
<div class="list-group" style="flex-direction: row; flex-wrap: wrap; gap: 1rem; justify-content: center;">
<div class="third-party-links">
<a href="https://addons.mozilla.org/fr/firefox/addon/shaarli/" target="_blank" class="btn btn-secondary">
<i class="mdi mdi-firefox" style="font-size: 1.2rem;"></i> Firefox
<i class="mdi mdi-firefox"></i> Firefox
</a>
<a href="https://chromewebstore.google.com/detail/add-to-shaarli/jhfblapoehcfajokolimghdfmeeakbee" target="_blank" class="btn btn-secondary">
<i class="mdi mdi-google-chrome" style="font-size: 1.2rem;"></i> Chrome
<i class="mdi mdi-google-chrome"></i> Chrome
</a>
<a href="https://f-droid.org/fr/packages/com.dimtion.shaarlier/" target="_blank" class="btn btn-secondary">
<i class="mdi mdi-android" style="font-size: 1.2rem;"></i> Shaarlier
<i class="mdi mdi-android"></i> Shaarlier
</a>
<a href="https://stakali.toneiv.eu/" target="_blank" class="btn btn-secondary">
<i class="mdi mdi-android" style="font-size: 1.2rem;"></i> Stakali
<i class="mdi mdi-android"></i> Stakali
</a>
<a href="https://github.com/lockcp/ShaarliOS" target="_blank" class="btn btn-secondary">
<i class="mdi mdi-apple-ios" style="font-size: 1.2rem;"></i> iOS
<i class="mdi mdi-apple-ios"></i> iOS
</a>
</div>
<p class="text-center text-muted" style="margin-top: 1.5rem;">